mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:06:04 +00:00
[UCRT] Import Microsoft.Windows.SDK.CRTSource version 10.0.22621.3
Imported from https://www.nuget.org/packages/Microsoft.Windows.SDK.CRTSource/10.0.22621.3 License: MIT
This commit is contained in:
parent
f1b60c66f0
commit
04e0dc4a7a
568 changed files with 115483 additions and 0 deletions
224
sdk/lib/ucrt/string/amd64/strcat.asm
Normal file
224
sdk/lib/ucrt/string/amd64/strcat.asm
Normal file
|
@ -0,0 +1,224 @@
|
|||
title strcat - concatenate (append) one string to another
|
||||
;***
|
||||
;strcat.asm - contains strcat() and strcpy() routines
|
||||
;
|
||||
; Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
;
|
||||
;Purpose:
|
||||
; STRCAT concatenates (appends) a copy of the source string to the
|
||||
; end of the destination string, returning the destination string.
|
||||
;
|
||||
;*******************************************************************************
|
||||
include ksamd64.inc
|
||||
subttl "strcat"
|
||||
;***
|
||||
;char *strcat(dst, src) - concatenate (append) one string to another
|
||||
;
|
||||
;Purpose:
|
||||
; Concatenates src onto the end of dest. Assumes enough
|
||||
; space in dest.
|
||||
;
|
||||
; Algorithm:
|
||||
; char * strcat (char * dst, char * src)
|
||||
; {
|
||||
; char * cp = dst;
|
||||
;
|
||||
; while( *cp )
|
||||
; ++cp; /* Find end of dst */
|
||||
; while( *cp++ = *src++ )
|
||||
; ; /* Copy src to end of dst */
|
||||
; return( dst );
|
||||
; }
|
||||
;
|
||||
;Entry:
|
||||
; char *dst - string to which "src" is to be appended
|
||||
; const char *src - string to be appended to the end of "dst"
|
||||
;
|
||||
;Exit:
|
||||
; The address of "dst" in EAX
|
||||
;
|
||||
;Uses:
|
||||
; EAX, ECX
|
||||
;
|
||||
;Exceptions:
|
||||
;
|
||||
;*******************************************************************************
|
||||
|
||||
;***
|
||||
;char *strcpy(dst, src) - copy one string over another
|
||||
;
|
||||
;Purpose:
|
||||
; Copies the string src into the spot specified by
|
||||
; dest; assumes enough room.
|
||||
;
|
||||
; Algorithm:
|
||||
; char * strcpy (char * dst, char * src)
|
||||
; {
|
||||
; char * cp = dst;
|
||||
;
|
||||
; while( *cp++ = *src++ )
|
||||
; ; /* Copy src over dst */
|
||||
; return( dst );
|
||||
; }
|
||||
;
|
||||
;Entry:
|
||||
; char * dst - string over which "src" is to be copied
|
||||
; const char * src - string to be copied over "dst"
|
||||
;
|
||||
;Exit:
|
||||
; The address of "dst" in EAX
|
||||
;
|
||||
;Uses:
|
||||
; EAX, ECX
|
||||
;
|
||||
;Exceptions:
|
||||
;*******************************************************************************
|
||||
|
||||
public ___entry_from_strcat_in_strcpy
|
||||
LEAF_ENTRY_ARG2 strcat, _TEXT, dst:ptr byte, src:ptr byte
|
||||
|
||||
OPTION PROLOGUE:NONE, EPILOGUE:NONE
|
||||
|
||||
mov r11, rcx
|
||||
test cl, 7
|
||||
jz strcat_loop_begin
|
||||
|
||||
strcat_copy_head_loop_begin:
|
||||
mov al, [rcx]
|
||||
test al, al
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
test cl, 7
|
||||
jnz strcat_copy_head_loop_begin
|
||||
|
||||
strcat_loop_begin:
|
||||
mov rax, [rcx]
|
||||
mov r10, rax
|
||||
mov r9, 7efefefefefefeffh
|
||||
add r9, r10
|
||||
xor r10, -1
|
||||
xor r10, r9
|
||||
add rcx, 8
|
||||
mov r9, 8101010101010100h
|
||||
test r10, r9
|
||||
je strcat_loop_begin
|
||||
sub rcx, 8
|
||||
|
||||
strcat_loop_end:
|
||||
test al, al
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
shr rax, 16
|
||||
test al, al
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
shr rax, 16
|
||||
test al, al
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
shr eax, 16
|
||||
test al, al
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz ___entry_from_strcat_in_strcpy
|
||||
inc rcx
|
||||
jmp strcat_loop_begin
|
||||
|
||||
LEAF_END strcat, _TEXT
|
||||
|
||||
LEAF_ENTRY_ARG2 strcpy, _TEXT, dst:ptr byte, src:ptr byte
|
||||
|
||||
OPTION PROLOGUE:NONE, EPILOGUE:NONE
|
||||
|
||||
mov r11, rcx
|
||||
strcat_copy:
|
||||
___entry_from_strcat_in_strcpy=strcat_copy
|
||||
; align the SOURCE so we never page fault
|
||||
; dest pointer alignment not important
|
||||
sub rcx, rdx ; combine pointers
|
||||
test dl, 7
|
||||
jz qword_loop_entrance
|
||||
|
||||
copy_head_loop_begin:
|
||||
mov al, [rdx]
|
||||
mov [rdx+rcx], al
|
||||
test al, al
|
||||
jz byte_exit
|
||||
inc rdx
|
||||
test dl, 7
|
||||
jnz copy_head_loop_begin
|
||||
jmp qword_loop_entrance
|
||||
|
||||
byte_exit:
|
||||
mov rax, r11
|
||||
ret
|
||||
|
||||
qword_loop_begin:
|
||||
mov [rdx+rcx], rax
|
||||
add rdx, 8
|
||||
qword_loop_entrance:
|
||||
mov rax, [rdx]
|
||||
mov r9, 7efefefefefefeffh
|
||||
add r9, rax
|
||||
mov r10, rax
|
||||
xor r10, -1
|
||||
xor r10, r9
|
||||
mov r9, 8101010101010100h
|
||||
test r10, r9
|
||||
jz qword_loop_begin
|
||||
|
||||
qword_loop_end:
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
shr rax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
shr rax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
shr eax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strcat_exit
|
||||
inc rdx
|
||||
jmp qword_loop_entrance
|
||||
|
||||
strcat_exit:
|
||||
mov rax, r11
|
||||
ret
|
||||
|
||||
LEAF_END strcpy, _TEXT
|
||||
|
||||
end
|
130
sdk/lib/ucrt/string/amd64/strcmp.asm
Normal file
130
sdk/lib/ucrt/string/amd64/strcmp.asm
Normal file
|
@ -0,0 +1,130 @@
|
|||
page ,132
|
||||
title strcmp.asm - compare two strings
|
||||
;***
|
||||
;strcmp.asm - routine to compare two strings (for equal, less, or greater)
|
||||
;
|
||||
; Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
;
|
||||
;Purpose:
|
||||
; STRCMP compares two strings and returns an integer
|
||||
; to indicate whether the first is less than the second, the two are
|
||||
; equal, or whether the first is greater than the second, respectively.
|
||||
; Comparison is done byte by byte on an UNSIGNED basis, which is to
|
||||
; say that Null (0) is less than any other character (1-255).
|
||||
;
|
||||
;*******************************************************************************
|
||||
include ksamd64.inc
|
||||
subttl "strcmp"
|
||||
;***
|
||||
;strcmp - compare two strings, returning less than, equal to, or greater than
|
||||
;
|
||||
;Purpose:
|
||||
; Compares two string, determining their ordinal order. Unsigned
|
||||
; comparison is used.
|
||||
;
|
||||
; Algorithm:
|
||||
; int strcmp ( src , dst )
|
||||
; unsigned char *src;
|
||||
; unsigned char *dst;
|
||||
; {
|
||||
; int ret = 0 ;
|
||||
;
|
||||
; while( ! (ret = *src - *dst) && *dst)
|
||||
; ++src, ++dst;
|
||||
;
|
||||
; if ( ret < 0 )
|
||||
; ret = -1 ;
|
||||
; else if ( ret > 0 )
|
||||
; ret = 1 ;
|
||||
;
|
||||
; return( ret );
|
||||
; }
|
||||
;
|
||||
;Entry:
|
||||
; const char * src - string for left-hand side of comparison
|
||||
; const char * dst - string for right-hand side of comparison
|
||||
;
|
||||
;Exit:
|
||||
; AX < 0, 0, or >0, indicating whether the first string is
|
||||
; Less than, Equal to, or Greater than the second string.
|
||||
;
|
||||
;Uses:
|
||||
; CX, DX
|
||||
;
|
||||
;Exceptions:
|
||||
;
|
||||
;*******************************************************************************
|
||||
|
||||
CHAR_TYPE EQU BYTE
|
||||
CHAR_PTR EQU BYTE PTR
|
||||
CHAR_SIZE = sizeof CHAR_TYPE
|
||||
|
||||
BLK_TYPE EQU QWORD
|
||||
BLK_PTR EQU QWORD PTR
|
||||
BLK_SIZE = sizeof BLK_TYPE
|
||||
|
||||
;PAGE_SIZE = 1000h
|
||||
PAGE_MASK = PAGE_SIZE - 1 ; mask for offset in MM page
|
||||
PAGE_SAFE_BLK = PAGE_SIZE - BLK_SIZE ; maximum offset for safe block compare
|
||||
|
||||
LEAF_ENTRY_ARG2 strcmp, _TEXT, str1:ptr byte, str2:ptr byte
|
||||
|
||||
OPTION PROLOGUE:NONE, EPILOGUE:NONE
|
||||
|
||||
; rcx = src
|
||||
; rdx = dst
|
||||
|
||||
sub rdx, rcx
|
||||
test cl, (BLK_SIZE - 1)
|
||||
jz qword_loop_enter
|
||||
|
||||
comp_head_loop_begin:
|
||||
movzx eax, CHAR_PTR[rcx]
|
||||
cmp al, CHAR_PTR[rdx+rcx]
|
||||
jnz return_not_equal
|
||||
|
||||
inc rcx
|
||||
|
||||
test al, al
|
||||
jz return_equal
|
||||
|
||||
test cl, (BLK_SIZE - 1)
|
||||
jnz comp_head_loop_begin
|
||||
|
||||
qword_loop_enter:
|
||||
|
||||
mov r11, 8080808080808080h
|
||||
mov r10, 0fefefefefefefeffh
|
||||
|
||||
qword_loop_begin:
|
||||
lea eax, [edx+ecx]
|
||||
and eax, PAGE_MASK
|
||||
cmp eax, PAGE_SAFE_BLK
|
||||
ja comp_head_loop_begin
|
||||
|
||||
mov rax, BLK_PTR[rcx]
|
||||
cmp rax, BLK_PTR[rdx+rcx]
|
||||
|
||||
; mismatched string (or maybe null + garbage after)
|
||||
jne comp_head_loop_begin
|
||||
|
||||
; look for null terminator
|
||||
lea r9, [rax + r10]
|
||||
not rax
|
||||
add rcx, BLK_SIZE
|
||||
and rax, r9
|
||||
|
||||
test rax, r11 ; r11=8080808080808080h
|
||||
jz qword_loop_begin
|
||||
|
||||
return_equal:
|
||||
xor eax, eax ; gets all 64 bits
|
||||
ret
|
||||
|
||||
return_not_equal:
|
||||
sbb rax, rax ; AX=-1, CY=1 AX=0, CY=0
|
||||
or rax, 1
|
||||
ret
|
||||
|
||||
LEAF_END strcmp, _TEXT
|
||||
end
|
13
sdk/lib/ucrt/string/amd64/strcspn.c
Normal file
13
sdk/lib/ucrt/string/amd64/strcspn.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
/***
|
||||
*strcspn.c - Defines the strcspn function.
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
*Purpose:
|
||||
* The function strcspn is mostly common code with strspn in strspn.c.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define SSTRCSPN
|
||||
#define STRSPN_USE_SSE2
|
||||
#include "strspn.c"
|
130
sdk/lib/ucrt/string/amd64/strlen.asm
Normal file
130
sdk/lib/ucrt/string/amd64/strlen.asm
Normal file
|
@ -0,0 +1,130 @@
|
|||
page ,132
|
||||
title strlen - return the length of a null-terminated string
|
||||
;***
|
||||
;strlen.asm - contains strlen() routine
|
||||
;
|
||||
; Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
;
|
||||
;Purpose:
|
||||
; strlen returns the length of a null-terminated string,
|
||||
; not including the null byte itself.
|
||||
;
|
||||
;*******************************************************************************
|
||||
include ksamd64.inc
|
||||
subttl "strlen"
|
||||
;***
|
||||
;strlen - return the length of a null-terminated string
|
||||
;
|
||||
;Purpose:
|
||||
; Finds the length in bytes of the given string, not including
|
||||
; the final null character.
|
||||
;
|
||||
; Algorithm:
|
||||
; int strlen (const char * str)
|
||||
; {
|
||||
; int length = 0;
|
||||
;
|
||||
; while( *str++ )
|
||||
; ++length;
|
||||
;
|
||||
; return( length );
|
||||
; }
|
||||
;
|
||||
;Entry:
|
||||
; const char * str - string whose length is to be computed
|
||||
;
|
||||
;Exit:
|
||||
; EAX = length of the string "str", exclusive of the final null byte
|
||||
;
|
||||
;Uses:
|
||||
; EAX, ECX, EDX
|
||||
;
|
||||
;Exceptions:
|
||||
;
|
||||
;*******************************************************************************
|
||||
|
||||
LEAF_ENTRY_ARG1 strlen, _TEXT, buf:ptr byte
|
||||
|
||||
OPTION PROLOGUE:NONE, EPILOGUE:NONE
|
||||
|
||||
mov rax, rcx
|
||||
neg rcx ; for later
|
||||
test rax, 7
|
||||
jz main_loop_entry
|
||||
|
||||
byte 066h, 090h
|
||||
|
||||
byte_loop_begin:
|
||||
mov dl, [rax]
|
||||
inc rax
|
||||
test dl, dl
|
||||
jz return_byte_7
|
||||
test al, 7
|
||||
jnz byte_loop_begin
|
||||
|
||||
main_loop_entry:
|
||||
mov r8, 7efefefefefefeffh
|
||||
mov r11, 8101010101010100h
|
||||
|
||||
main_loop_begin:
|
||||
mov rdx, [rax]
|
||||
|
||||
mov r9, r8
|
||||
add rax, 8
|
||||
add r9, rdx
|
||||
not rdx
|
||||
xor rdx, r9
|
||||
and rdx, r11
|
||||
je main_loop_begin
|
||||
|
||||
main_loop_end:
|
||||
|
||||
mov rdx, [rax-8]
|
||||
|
||||
test dl, dl
|
||||
jz return_byte_0
|
||||
test dh, dh
|
||||
jz return_byte_1
|
||||
shr rdx, 16
|
||||
test dl, dl
|
||||
jz return_byte_2
|
||||
test dh, dh
|
||||
jz return_byte_3
|
||||
shr rdx, 16
|
||||
test dl, dl
|
||||
jz return_byte_4
|
||||
test dh, dh
|
||||
jz return_byte_5
|
||||
shr edx, 16
|
||||
test dl, dl
|
||||
jz return_byte_6
|
||||
test dh, dh
|
||||
jnz main_loop_begin
|
||||
|
||||
return_byte_7:
|
||||
lea rax, [rax+rcx-1]
|
||||
ret
|
||||
return_byte_6:
|
||||
lea rax, [rax+rcx-2]
|
||||
ret
|
||||
return_byte_5:
|
||||
lea rax, [rax+rcx-3]
|
||||
ret
|
||||
return_byte_4:
|
||||
lea rax, [rax+rcx-4]
|
||||
ret
|
||||
return_byte_3:
|
||||
lea rax, [rax+rcx-5]
|
||||
ret
|
||||
return_byte_2:
|
||||
lea rax, [rax+rcx-6]
|
||||
ret
|
||||
return_byte_1:
|
||||
lea rax, [rax+rcx-7]
|
||||
ret
|
||||
return_byte_0:
|
||||
lea rax, [rax+rcx-8]
|
||||
ret
|
||||
|
||||
LEAF_END strlen, _TEXT
|
||||
end
|
227
sdk/lib/ucrt/string/amd64/strncat.asm
Normal file
227
sdk/lib/ucrt/string/amd64/strncat.asm
Normal file
|
@ -0,0 +1,227 @@
|
|||
page ,132
|
||||
title strncat - append n chars of string1 to string2
|
||||
;***
|
||||
;strncat.asm - append n chars of string to new string
|
||||
;
|
||||
; Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
;
|
||||
;Purpose:
|
||||
; defines strncat() - appends n characters of string onto
|
||||
; end of other string
|
||||
;
|
||||
;*******************************************************************************
|
||||
include ksamd64.inc
|
||||
subttl "strncat"
|
||||
;***
|
||||
;char *strncat(front, back, count) - append count chars of back onto front
|
||||
;
|
||||
;Purpose:
|
||||
; Appends at most count characters of the string back onto the
|
||||
; end of front, and ALWAYS terminates with a null character.
|
||||
; If count is greater than the length of back, the length of back
|
||||
; is used instead. (Unlike strncpy, this routine does not pad out
|
||||
; to count characters).
|
||||
;
|
||||
; Algorithm:
|
||||
; char *
|
||||
; strncat (front, back, count)
|
||||
; char *front, *back;
|
||||
; unsigned count;
|
||||
; {
|
||||
; char *start = front;
|
||||
;
|
||||
; while (*front++)
|
||||
; ;
|
||||
; front--;
|
||||
; while (count--)
|
||||
; if (!(*front++ = *back++))
|
||||
; return(start);
|
||||
; *front = '\0';
|
||||
; return(start);
|
||||
; }
|
||||
;
|
||||
;Entry:
|
||||
; char * front - string to append onto
|
||||
; char * back - string to append
|
||||
; unsigned count - count of max characters to append
|
||||
;
|
||||
;Exit:
|
||||
; returns a pointer to string appended onto (front).
|
||||
;
|
||||
;Uses: ECX, EDX
|
||||
;
|
||||
;Exceptions:
|
||||
;
|
||||
;*******************************************************************************
|
||||
LEAF_ENTRY_ARG3 strncat, _TEXT, front:ptr byte, back:ptr byte, count:dword
|
||||
OPTION PROLOGUE:NONE, EPILOGUE:NONE
|
||||
|
||||
mov r11, rcx
|
||||
or r8, r8
|
||||
jz byte_exit
|
||||
test cl, 7
|
||||
jz strncat_loop_begin
|
||||
|
||||
strncat_copy_head_loop_begin:
|
||||
mov al, [rcx]
|
||||
test al, al
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
test cl, 7
|
||||
jnz strncat_copy_head_loop_begin
|
||||
|
||||
nop
|
||||
|
||||
strncat_loop_begin:
|
||||
mov rax, [rcx]
|
||||
mov r10, rax
|
||||
mov r9, 7efefefefefefeffh
|
||||
add r9, r10
|
||||
xor r10, -1
|
||||
xor r10, r9
|
||||
add rcx, 8
|
||||
mov r9, 8101010101010100h
|
||||
test r10, r9
|
||||
je strncat_loop_begin
|
||||
sub rcx, 8
|
||||
|
||||
strncat_loop_end:
|
||||
test al, al
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
shr rax, 16
|
||||
test al, al
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
shr rax, 16
|
||||
test al, al
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
shr eax, 16
|
||||
test al, al
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
test ah, ah
|
||||
jz strncat_copy
|
||||
inc rcx
|
||||
jmp strncat_loop_begin
|
||||
|
||||
strncat_copy:
|
||||
; align the SOURCE so we never page fault
|
||||
; dest pointer alignment not important
|
||||
sub rcx, rdx ; combine pointers
|
||||
test dl, 7
|
||||
jz qword_loop_entrance
|
||||
|
||||
copy_head_loop_begin:
|
||||
mov al, [rdx]
|
||||
mov [rdx+rcx], al
|
||||
test al, al
|
||||
jz byte_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz byte_null_end
|
||||
test dl, 7
|
||||
jnz copy_head_loop_begin
|
||||
jmp qword_loop_entrance
|
||||
|
||||
byte_null_end:
|
||||
xor al, al
|
||||
mov [rdx+rcx], al
|
||||
byte_exit:
|
||||
mov rax, r11
|
||||
ret
|
||||
|
||||
nop
|
||||
|
||||
qword_loop_begin:
|
||||
mov [rdx+rcx], rax
|
||||
add rdx, 8
|
||||
qword_loop_entrance:
|
||||
mov rax, [rdx]
|
||||
sub r8, 8
|
||||
jbe qword_loop_end
|
||||
mov r9, 7efefefefefefeffh
|
||||
add r9, rax
|
||||
mov r10, rax
|
||||
xor r10, -1
|
||||
xor r10, r9
|
||||
mov r9, 8101010101010100h
|
||||
test r10, r9
|
||||
jz qword_loop_begin
|
||||
|
||||
qword_loop_end:
|
||||
add r8, 8
|
||||
jz strncat_exit_2
|
||||
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncat_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncat_exit_2
|
||||
shr rax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncat_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncat_exit_2
|
||||
shr rax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncat_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncat_exit_2
|
||||
shr eax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncat_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz strncat_exit
|
||||
inc rdx
|
||||
dec r8
|
||||
jnz qword_loop_entrance
|
||||
|
||||
strncat_exit_2:
|
||||
xor al, al
|
||||
mov [rdx+rcx], al
|
||||
strncat_exit:
|
||||
mov rax, r11
|
||||
ret
|
||||
|
||||
LEAF_END strncat, _TEXT
|
||||
|
||||
end
|
125
sdk/lib/ucrt/string/amd64/strncmp.asm
Normal file
125
sdk/lib/ucrt/string/amd64/strncmp.asm
Normal file
|
@ -0,0 +1,125 @@
|
|||
page ,132
|
||||
title strncmp - compare first n chars of two strings
|
||||
;***
|
||||
;strncmp.asm - compare first n characters of two strings
|
||||
;
|
||||
; Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
;
|
||||
;Purpose:
|
||||
; defines strncmp() - compare first n characters of two strings
|
||||
; for ordinal order.
|
||||
;
|
||||
;*******************************************************************************
|
||||
include ksamd64.inc
|
||||
subttl "strncmp"
|
||||
;***
|
||||
;int strncmp(first, last, count) - compare first count chars of strings
|
||||
;
|
||||
;Purpose:
|
||||
; Compares two strings for ordinal order. The comparison stops
|
||||
; after: (1) a difference between the strings is found, (2) the end
|
||||
; of the strings is reached, or (3) count characters have been
|
||||
; compared.
|
||||
;
|
||||
; Algorithm:
|
||||
; int
|
||||
; strncmp (first, last, count)
|
||||
; char *first, *last;
|
||||
; unsigned count;
|
||||
; {
|
||||
; if (!count)
|
||||
; return(0);
|
||||
; while (--count && *first && *first == *last)
|
||||
; {
|
||||
; first++;
|
||||
; last++;
|
||||
; }
|
||||
; return(*first - *last);
|
||||
; }
|
||||
;
|
||||
;Entry:
|
||||
; char *first, *last - strings to compare
|
||||
; unsigned count - maximum number of characters to compare
|
||||
;
|
||||
;Exit:
|
||||
; returns <0 if first < last
|
||||
; returns 0 if first == last
|
||||
; returns >0 if first > last
|
||||
;
|
||||
;Uses:
|
||||
;
|
||||
;Exceptions:
|
||||
;
|
||||
;*******************************************************************************
|
||||
|
||||
LEAF_ENTRY_ARG3 strncmp, _TEXT, str1:ptr byte, str2:ptr byte, count:dword
|
||||
|
||||
OPTION PROLOGUE:NONE, EPILOGUE:NONE
|
||||
|
||||
; rcx = first
|
||||
; rdx = last
|
||||
; r8 = count
|
||||
|
||||
sub rdx, rcx
|
||||
|
||||
test r8, r8
|
||||
jz return_equal
|
||||
|
||||
test ecx, 7
|
||||
jz qword_loop_enter
|
||||
|
||||
comp_head_loop_begin:
|
||||
movzx eax, byte ptr[rcx]
|
||||
cmp al, byte ptr[rdx+rcx]
|
||||
jne return_not_equal
|
||||
|
||||
inc rcx
|
||||
|
||||
dec r8
|
||||
jz return_equal
|
||||
|
||||
test al, al
|
||||
jz return_equal
|
||||
|
||||
test rcx, 7
|
||||
jnz comp_head_loop_begin
|
||||
|
||||
qword_loop_enter:
|
||||
mov r11, 08080808080808080h
|
||||
mov r10, 0fefefefefefefeffh
|
||||
|
||||
qword_loop_begin:
|
||||
lea eax, [rdx+rcx]
|
||||
and eax, 0fffh
|
||||
cmp eax, 0ff8h
|
||||
ja comp_head_loop_begin
|
||||
|
||||
mov rax, qword ptr[rcx]
|
||||
cmp rax, qword ptr[rdx+rcx]
|
||||
jne comp_head_loop_begin
|
||||
|
||||
add rcx, 8
|
||||
|
||||
sub r8, 8
|
||||
jbe return_equal
|
||||
|
||||
lea r9, [r10+rax]
|
||||
not rax
|
||||
and rax, r9
|
||||
test rax, r11 ; 8080808080808080h
|
||||
|
||||
jz qword_loop_begin
|
||||
|
||||
return_equal:
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
; align 16
|
||||
|
||||
return_not_equal:
|
||||
sbb rax, rax ; AX=-1, CY=1 AX=0, CY=0
|
||||
or rax, 1
|
||||
ret
|
||||
|
||||
LEAF_END strncmp, _TEXT
|
||||
end
|
169
sdk/lib/ucrt/string/amd64/strncpy.asm
Normal file
169
sdk/lib/ucrt/string/amd64/strncpy.asm
Normal file
|
@ -0,0 +1,169 @@
|
|||
page ,132
|
||||
title strncpy - copy at most n characters of string
|
||||
;***
|
||||
;strncpy.asm - copy at most n characters of string
|
||||
;
|
||||
; Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
;
|
||||
;Purpose:
|
||||
; defines strncpy() - copy at most n characters of string
|
||||
;
|
||||
;*******************************************************************************
|
||||
; Look at strncat.asm for this file
|
||||
include ksamd64.inc
|
||||
subttl "strncpy"
|
||||
|
||||
LEAF_ENTRY_ARG3 strncpy, _TEXT, dst:ptr byte, src:ptr byte, count:dword
|
||||
OPTION PROLOGUE:NONE, EPILOGUE:NONE
|
||||
|
||||
; align the SOURCE so we never page fault
|
||||
; dest pointer alignment not important
|
||||
|
||||
mov r11, rcx
|
||||
or r8, r8
|
||||
jz strncpy_exit
|
||||
sub rcx, rdx ; combine pointers
|
||||
test dl, 7
|
||||
jz qword_loop_entrance
|
||||
|
||||
copy_head_loop_begin:
|
||||
mov al, [rdx]
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit
|
||||
test dl, 7
|
||||
jnz copy_head_loop_begin
|
||||
jmp qword_loop_entrance
|
||||
|
||||
strncpy_exit:
|
||||
mov rax, r11
|
||||
ret
|
||||
|
||||
qword_loop_begin:
|
||||
mov [rdx+rcx], rax
|
||||
add rdx, 8
|
||||
qword_loop_entrance:
|
||||
mov rax, [rdx]
|
||||
sub r8, 8
|
||||
jbe qword_loop_end
|
||||
mov r9, 7efefefefefefeffh
|
||||
add r9, rax
|
||||
mov r10, rax
|
||||
xor r10, -1
|
||||
xor r10, r9
|
||||
mov r9, 8101010101010100h
|
||||
test r10, r9
|
||||
jz qword_loop_begin
|
||||
|
||||
qword_loop_end:
|
||||
add r8, 8
|
||||
jz strncpy_exit_2
|
||||
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit_2
|
||||
shr rax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit_2
|
||||
shr rax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit_2
|
||||
shr eax, 16
|
||||
test al, al
|
||||
mov [rdx+rcx], al
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jz strncpy_exit_2
|
||||
test ah, ah
|
||||
mov [rdx+rcx], ah
|
||||
jz filler
|
||||
inc rdx
|
||||
dec r8
|
||||
jnz qword_loop_entrance
|
||||
|
||||
strncpy_exit_2:
|
||||
mov rax, r11
|
||||
ret
|
||||
|
||||
;this is really just memset
|
||||
filler:
|
||||
add rcx, rdx
|
||||
xor rdx, rdx
|
||||
cmp r8, 16
|
||||
jb tail ; a quickie
|
||||
aligner1:
|
||||
test cl, 7
|
||||
jz aligned
|
||||
inc rcx
|
||||
mov [rcx], dl
|
||||
dec r8
|
||||
jmp aligner1
|
||||
aligned:
|
||||
sub r8, 32
|
||||
jb tail_8_enter
|
||||
loop32:
|
||||
mov [rcx], rdx
|
||||
mov [rcx+8], rdx
|
||||
mov [rcx+16], rdx
|
||||
mov [rcx+24], rdx
|
||||
add rcx, 32
|
||||
sub r8, 32
|
||||
jae loop32
|
||||
|
||||
tail_8_enter:
|
||||
add r8, 32 ; get back the value
|
||||
tail_8_begin:
|
||||
sub r8, 8
|
||||
jb tail_enter
|
||||
mov [rcx], rdx
|
||||
add rcx, 8
|
||||
jmp tail_8_begin
|
||||
|
||||
tail_enter:
|
||||
add r8, 8 ; get back the value
|
||||
tail:
|
||||
sub r8, 1
|
||||
jb tail_finish
|
||||
mov [rcx], dl
|
||||
inc rcx
|
||||
jmp tail
|
||||
tail_finish:
|
||||
mov rax, r11
|
||||
ret
|
||||
|
||||
LEAF_END strncpy, _TEXT
|
||||
|
||||
end
|
13
sdk/lib/ucrt/string/amd64/strpbrk.c
Normal file
13
sdk/lib/ucrt/string/amd64/strpbrk.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
/***
|
||||
*strpbrk.c - Defines the strpbrk function.
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
*Purpose:
|
||||
* The function strpbrk is mostly common code with strspn in strspn.c.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define SSTRPBRK
|
||||
#define STRSPN_USE_SSE2
|
||||
#include "strspn.c"
|
502
sdk/lib/ucrt/string/amd64/strspn.c
Normal file
502
sdk/lib/ucrt/string/amd64/strspn.c
Normal file
|
@ -0,0 +1,502 @@
|
|||
/***
|
||||
*strspn.c - find length of initial substring of chars from a control string
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
*Purpose:
|
||||
* defines strspn() - finds the length of the initial substring of
|
||||
* a string consisting entirely of characters from a control string.
|
||||
*
|
||||
* defines strcspn()- finds the length of the initial substring of
|
||||
* a string consisting entirely of characters not in a control string.
|
||||
*
|
||||
* defines strpbrk()- finds the index of the first character in a string
|
||||
* that is not in a control string
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED) // 26018 Prefast doesn't understand reading past buffer but staying on same page.
|
||||
#pragma warning(disable:__WARNING_RETURNING_BAD_RESULT) // 28196
|
||||
|
||||
/* Determine which routine we're compiling for (default to STRSPN) */
|
||||
#define _STRSPN 1
|
||||
#define _STRCSPN 2
|
||||
#define _STRPBRK 3
|
||||
|
||||
#if defined (SSTRCSPN)
|
||||
#define ROUTINE _STRCSPN
|
||||
#elif defined (SSTRPBRK)
|
||||
#define ROUTINE _STRPBRK
|
||||
#else
|
||||
#define ROUTINE _STRSPN
|
||||
#define STRSPN_USE_SSE2
|
||||
#endif
|
||||
|
||||
/***
|
||||
*int strspn(string, control) - find init substring of control chars
|
||||
*
|
||||
*Purpose:
|
||||
* Finds the index of the first character in string that does belong
|
||||
* to the set of characters specified by control. This is
|
||||
* equivalent to the length of the initial substring of string that
|
||||
* consists entirely of characters from control. The '\0' character
|
||||
* that terminates control is not considered in the matching process.
|
||||
*
|
||||
*Entry:
|
||||
* char *string - string to search
|
||||
* char *control - string containing characters not to search for
|
||||
*
|
||||
*Exit:
|
||||
* returns index of first char in string not in control
|
||||
*
|
||||
*Exceptions:
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/***
|
||||
*int strcspn(string, control) - search for init substring w/o control chars
|
||||
*
|
||||
*Purpose:
|
||||
* returns the index of the first character in string that belongs
|
||||
* to the set of characters specified by control. This is equivalent
|
||||
* to the length of the length of the initial substring of string
|
||||
* composed entirely of characters not in control. Null chars not
|
||||
* considered.
|
||||
*
|
||||
*Entry:
|
||||
* char *string - string to search
|
||||
* char *control - set of characters not allowed in init substring
|
||||
*
|
||||
*Exit:
|
||||
* returns the index of the first char in string
|
||||
* that is in the set of characters specified by control.
|
||||
*
|
||||
*Exceptions:
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/***
|
||||
*char *strpbrk(string, control) - scans string for a character from control
|
||||
*
|
||||
*Purpose:
|
||||
* Finds the first occurence in string of any character from
|
||||
* the control string.
|
||||
*
|
||||
*Entry:
|
||||
* char *string - string to search in
|
||||
* char *control - string containing characters to search for
|
||||
*
|
||||
*Exit:
|
||||
* returns a pointer to the first character from control found
|
||||
* in string.
|
||||
* returns NULL if string and control have no characters in common.
|
||||
*
|
||||
*Exceptions:
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Routine prototype */
|
||||
#if ROUTINE == _STRSPN
|
||||
#if defined(STRSPN_USE_SSE2)
|
||||
__declspec(noinline)
|
||||
static size_t __cdecl fallbackMethod(
|
||||
#else
|
||||
size_t __cdecl strspn (
|
||||
#endif
|
||||
#elif ROUTINE == _STRCSPN
|
||||
#if defined(STRSPN_USE_SSE2)
|
||||
__declspec(noinline)
|
||||
static size_t __cdecl fallbackMethod(
|
||||
#else
|
||||
size_t __cdecl strcspn (
|
||||
#endif
|
||||
#else /* ROUTINE == _STRCSPN */
|
||||
#if defined(STRSPN_USE_SSE2)
|
||||
__declspec(noinline)
|
||||
static char * __cdecl fallbackMethod(
|
||||
#else
|
||||
char * __cdecl strpbrk (
|
||||
#endif
|
||||
#endif /* ROUTINE == _STRCSPN */
|
||||
const char * string,
|
||||
const char * control
|
||||
)
|
||||
{
|
||||
const unsigned char *str = (unsigned char const*)string;
|
||||
const unsigned char *ctrl = (unsigned char const*)control;
|
||||
|
||||
unsigned char map[32];
|
||||
int count;
|
||||
|
||||
/* Clear out bit map */
|
||||
for (count=0; count<32; count++)
|
||||
map[count] = 0;
|
||||
|
||||
/* Set bits in control map */
|
||||
while (*ctrl)
|
||||
{
|
||||
map[*ctrl >> 3] |= (1 << (*ctrl & 7));
|
||||
ctrl++;
|
||||
}
|
||||
|
||||
#if ROUTINE == _STRSPN
|
||||
|
||||
/* 1st char NOT in control map stops search */
|
||||
if (*str)
|
||||
{
|
||||
count=0;
|
||||
while (map[*str >> 3] & (1 << (*str & 7)))
|
||||
{
|
||||
count++;
|
||||
str++;
|
||||
}
|
||||
return(count);
|
||||
}
|
||||
return(0);
|
||||
|
||||
#elif ROUTINE == _STRCSPN
|
||||
|
||||
/* 1st char in control map stops search */
|
||||
count=0;
|
||||
map[0] |= 1; /* null chars not considered */
|
||||
while (!(map[*str >> 3] & (1 << (*str & 7))))
|
||||
{
|
||||
count++;
|
||||
str++;
|
||||
}
|
||||
return(count);
|
||||
|
||||
#else /* ROUTINE == _STRCSPN */
|
||||
|
||||
/* 1st char in control map stops search */
|
||||
while (*str)
|
||||
{
|
||||
if (map[*str >> 3] & (1 << (*str & 7)))
|
||||
return((char *)str);
|
||||
str++;
|
||||
}
|
||||
return(NULL);
|
||||
|
||||
#endif /* ROUTINE == _STRCSPN */
|
||||
|
||||
}
|
||||
|
||||
#if defined(STRSPN_USE_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#pragma optimize("t", on)
|
||||
|
||||
/* Routine prototype */
|
||||
#if ROUTINE == _STRSPN
|
||||
size_t __cdecl strspn (
|
||||
#elif ROUTINE == _STRCSPN
|
||||
size_t __cdecl strcspn (
|
||||
#else /* ROUTINE == _STRCSPN */
|
||||
char * __cdecl strpbrk (
|
||||
|
||||
#endif /* ROUTINE == _STRCSPN */
|
||||
const char * string, const char * control)
|
||||
{
|
||||
unsigned long long shift = (unsigned long long) control & 0xf;
|
||||
|
||||
// Mask off the lower bits of the address to get a 16-byte aligned pointer
|
||||
char * alignedControl = (char *) control - shift;
|
||||
|
||||
// Load 16 bytes. This will not cross a page boundary but will have spurious data
|
||||
__m128i search = _mm_loadu_si128((__m128i *) alignedControl);
|
||||
__m128i zero = _mm_xor_si128(zero, zero);
|
||||
__m128i temp, tempMask, smearedChar;
|
||||
unsigned int mask, terminatorSeen = 0;
|
||||
unsigned long bitCount;
|
||||
|
||||
// Sse2 provides immediate shifts of the full 128 bit register.
|
||||
// Shift out the spurious data on the right and shift in zeros.
|
||||
switch (shift)
|
||||
{
|
||||
case 1:
|
||||
search = _mm_srli_si128(search, 1);
|
||||
break;
|
||||
case 2:
|
||||
search = _mm_srli_si128(search, 2);
|
||||
break;
|
||||
case 3:
|
||||
search = _mm_srli_si128(search, 3);
|
||||
break;
|
||||
case 4:
|
||||
search = _mm_srli_si128(search, 4);
|
||||
break;
|
||||
case 5:
|
||||
search = _mm_srli_si128(search, 5);
|
||||
break;
|
||||
case 6:
|
||||
search = _mm_srli_si128(search, 6);
|
||||
break;
|
||||
case 7:
|
||||
search = _mm_srli_si128(search, 7);
|
||||
break;
|
||||
case 8:
|
||||
search = _mm_srli_si128(search, 8);
|
||||
break;
|
||||
case 9:
|
||||
search = _mm_srli_si128(search, 9);
|
||||
break;
|
||||
case 10:
|
||||
search = _mm_srli_si128(search, 10);
|
||||
break;
|
||||
case 11:
|
||||
search = _mm_srli_si128(search, 11);
|
||||
break;
|
||||
case 12:
|
||||
search = _mm_srli_si128(search, 12);
|
||||
break;
|
||||
case 13:
|
||||
search = _mm_srli_si128(search, 13);
|
||||
break;
|
||||
case 14:
|
||||
search = _mm_srli_si128(search, 14);
|
||||
break;
|
||||
case 15:
|
||||
search = _mm_srli_si128(search, 15);
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Search for zero bytes in this initial string
|
||||
temp = _mm_cmpeq_epi8(search, zero);
|
||||
mask = _mm_movemask_epi8(temp);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
// We found zeros and now need to mask away the spurious data that may follow
|
||||
(void) _BitScanForward(&bitCount, mask);
|
||||
|
||||
terminatorSeen = (shift == 0) ? 1 : (bitCount < (16 - shift));
|
||||
|
||||
switch (16 - bitCount)
|
||||
{
|
||||
case 1:
|
||||
search = _mm_slli_si128(search, 1);
|
||||
search = _mm_srli_si128(search, 1);
|
||||
break;
|
||||
case 2:
|
||||
search = _mm_slli_si128(search, 2);
|
||||
search = _mm_srli_si128(search, 2);
|
||||
break;
|
||||
case 3:
|
||||
search = _mm_slli_si128(search, 3);
|
||||
search = _mm_srli_si128(search, 3);
|
||||
break;
|
||||
case 4:
|
||||
search = _mm_slli_si128(search, 4);
|
||||
search = _mm_srli_si128(search, 4);
|
||||
break;
|
||||
case 5:
|
||||
search = _mm_slli_si128(search, 5);
|
||||
search = _mm_srli_si128(search, 5);
|
||||
break;
|
||||
case 6:
|
||||
search = _mm_slli_si128(search, 6);
|
||||
search = _mm_srli_si128(search, 6);
|
||||
break;
|
||||
case 7:
|
||||
search = _mm_slli_si128(search, 7);
|
||||
search = _mm_srli_si128(search, 7);
|
||||
break;
|
||||
case 8:
|
||||
search = _mm_slli_si128(search, 8);
|
||||
search = _mm_srli_si128(search, 8);
|
||||
break;
|
||||
case 9:
|
||||
search = _mm_slli_si128(search, 9);
|
||||
search = _mm_srli_si128(search, 9);
|
||||
break;
|
||||
case 10:
|
||||
search = _mm_slli_si128(search, 10);
|
||||
search = _mm_srli_si128(search, 10);
|
||||
break;
|
||||
case 11:
|
||||
search = _mm_slli_si128(search, 11);
|
||||
search = _mm_srli_si128(search, 11);
|
||||
break;
|
||||
case 12:
|
||||
search = _mm_slli_si128(search, 12);
|
||||
search = _mm_srli_si128(search, 12);
|
||||
break;
|
||||
case 13:
|
||||
search = _mm_slli_si128(search, 13);
|
||||
search = _mm_srli_si128(search, 13);
|
||||
break;
|
||||
case 14:
|
||||
search = _mm_slli_si128(search, 14);
|
||||
search = _mm_srli_si128(search, 14);
|
||||
break;
|
||||
case 15:
|
||||
search = _mm_slli_si128(search, 15);
|
||||
search = _mm_srli_si128(search, 15);
|
||||
break;
|
||||
case 16:
|
||||
search = zero;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (shift == 0)
|
||||
{
|
||||
// We loaded 16 bytes and found no zero. Check if the first byte in
|
||||
// the next 16-byte aligned block is zero. This load will not page fault
|
||||
// on a correct program since we have not see the terminator.
|
||||
if (*(alignedControl + 1) == 0)
|
||||
{
|
||||
terminatorSeen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have 16 bytes and have not seen the terminator. Fallback to
|
||||
// non-Sse2 version.
|
||||
return fallbackMethod(string, control);
|
||||
}
|
||||
}
|
||||
|
||||
// If was have not seen the string terminator, attempt to piece-together a search
|
||||
// mask of bytes from those in the next 16-byte aligned group that follows.
|
||||
// We will allow at most 16 bytes in the search string.
|
||||
if (!terminatorSeen)
|
||||
{
|
||||
// Go get the next 16 bytes, again this will not page fault.
|
||||
alignedControl += 16;
|
||||
temp = _mm_loadu_si128((__m128i *) alignedControl);
|
||||
|
||||
tempMask = _mm_cmpeq_epi8(temp, zero);
|
||||
terminatorSeen = _mm_movemask_epi8(tempMask);
|
||||
|
||||
if (!terminatorSeen)
|
||||
{
|
||||
return fallbackMethod(string, control);
|
||||
}
|
||||
|
||||
(void) _BitScanForward(&bitCount, terminatorSeen);
|
||||
|
||||
if ((16 - shift + bitCount) > 16)
|
||||
{
|
||||
return fallbackMethod(string, control);
|
||||
}
|
||||
|
||||
// Shift the 2nd part of the search mask into place with the 16 bytes
|
||||
switch (16 - bitCount)
|
||||
{
|
||||
case 1:
|
||||
temp = _mm_slli_si128(temp, 1);
|
||||
break;
|
||||
case 2:
|
||||
temp = _mm_slli_si128(temp, 2);
|
||||
break;
|
||||
case 3:
|
||||
temp = _mm_slli_si128(temp, 3);
|
||||
break;
|
||||
case 4:
|
||||
temp = _mm_slli_si128(temp, 4);
|
||||
break;
|
||||
case 5:
|
||||
temp = _mm_slli_si128(temp, 5);
|
||||
break;
|
||||
case 6:
|
||||
temp = _mm_slli_si128(temp, 6);
|
||||
break;
|
||||
case 7:
|
||||
temp = _mm_slli_si128(temp, 7);
|
||||
break;
|
||||
case 8:
|
||||
temp = _mm_slli_si128(temp, 8);
|
||||
break;
|
||||
case 9:
|
||||
temp = _mm_slli_si128(temp, 9);
|
||||
break;
|
||||
case 10:
|
||||
temp = _mm_slli_si128(temp, 10);
|
||||
break;
|
||||
case 11:
|
||||
temp = _mm_slli_si128(temp, 11);
|
||||
break;
|
||||
case 12:
|
||||
temp = _mm_slli_si128(temp, 12);
|
||||
break;
|
||||
case 13:
|
||||
temp = _mm_slli_si128(temp, 13);
|
||||
break;
|
||||
case 14:
|
||||
temp = _mm_slli_si128(temp, 14);
|
||||
break;
|
||||
case 15:
|
||||
temp = _mm_slli_si128(temp, 15);
|
||||
break;
|
||||
case 16:
|
||||
temp = zero;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Or the two parts together to obtain a single up-to 16-byte search mask
|
||||
search = _mm_or_si128(search, temp);
|
||||
}
|
||||
|
||||
// Now loop through the string do a 16-compare with our search mask
|
||||
#if (ROUTINE == _STRSPN) || (ROUTINE == _STRCSPN)
|
||||
size_t count = 0;
|
||||
#endif
|
||||
while (*string)
|
||||
{
|
||||
int smear = (int) *string;
|
||||
// Get the byte in a register
|
||||
smearedChar = _mm_cvtsi32_si128(smear);
|
||||
|
||||
// The following 3 instructions smear this one character through each byte of the 16-byte register
|
||||
smearedChar = _mm_unpacklo_epi8(smearedChar, smearedChar);
|
||||
smearedChar = _mm_unpacklo_epi8(smearedChar, smearedChar);
|
||||
smearedChar = _mm_shuffle_epi32(smearedChar, 0);
|
||||
|
||||
// Look for a match
|
||||
temp = _mm_cmpeq_epi8(search, smearedChar);
|
||||
mask = _mm_movemask_epi8(temp);
|
||||
|
||||
#if (ROUTINE == _STRSPN)
|
||||
// Break if no match
|
||||
if (!mask)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
string++;
|
||||
count++;
|
||||
#elif (ROUTINE == _STRCSPN)
|
||||
// Break on first match
|
||||
if (mask)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
string++;
|
||||
count++;
|
||||
#else // strpbrk case
|
||||
// Return current string location on a match
|
||||
if (mask)
|
||||
{
|
||||
return (char *) string;
|
||||
}
|
||||
|
||||
string++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (ROUTINE == _STRSPN) || (ROUTINE == _STRCSPN)
|
||||
return count;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue