xref: /reactos/sdk/lib/ucrt/string/amd64/strncat.s (revision 94eb4751)
1#include <asm.inc>
2#include <ksamd64.inc>
3.code64
4#if 0
5        page    ,132
6        title   strncat - append n chars of string1 to string2
7;***
8;strncat.asm - append n chars of string to new string
9;
10;       Copyright (c) Microsoft Corporation. All rights reserved.
11;
12;Purpose:
13;       defines strncat() - appends n characters of string onto
14;       end of other string
15;
16;*******************************************************************************
17include ksamd64.inc
18        subttl  "strncat"
19;***
20;char *strncat(front, back, count) - append count chars of back onto front
21;
22;Purpose:
23;       Appends at most count characters of the string back onto the
24;       end of front, and ALWAYS terminates with a null character.
25;       If count is greater than the length of back, the length of back
26;       is used instead.  (Unlike strncpy, this routine does not pad out
27;       to count characters).
28;
29;       Algorithm:
30;       char *
31;       strncat (front, back, count)
32;           char *front, *back;
33;           unsigned count;
34;       {
35;           char *start = front;
36;
37;           while (*front++)
38;               ;
39;           front--;
40;           while (count--)
41;               if (!(*front++ = *back++))
42;                   return(start);
43;           *front = '\0';
44;           return(start);
45;       }
46;
47;Entry:
48;       char *   front - string to append onto
49;       char *   back  - string to append
50;       unsigned count - count of max characters to append
51;
52;Exit:
53;       returns a pointer to string appended onto (front).
54;
55;Uses:  ECX, EDX
56;
57;Exceptions:
58;
59;*******************************************************************************
60#endif
61LEAF_ENTRY_ARG3 strncat, _TEXT, front_ptr_byte, back_ptr_byte, count_dword
62    //OPTION PROLOGUE:NONE, EPILOGUE:NONE
63
64    mov     r11, rcx
65    or      r8, r8
66    jz      byte_exit
67    test    cl, 7
68    jz      strncat_loop_begin
69
70strncat_copy_head_loop_begin:
71    mov     al, [rcx]
72    test    al, al
73    jz      strncat_copy
74    inc     rcx
75    test    cl, 7
76    jnz     strncat_copy_head_loop_begin
77
78    nop
79
80strncat_loop_begin:
81    mov     rax, [rcx]
82    mov     r10, rax
83    mov     r9, HEX(7efefefefefefeff)
84    add     r9, r10
85    xor     r10, -1
86    xor     r10, r9
87    add     rcx, 8
88    mov     r9, HEX(8101010101010100)
89    test    r10, r9
90    je      strncat_loop_begin
91    sub     rcx, 8
92
93strncat_loop_end:
94    test    al, al
95    jz      strncat_copy
96    inc     rcx
97    test    ah, ah
98    jz      strncat_copy
99    inc     rcx
100    shr     rax, 16
101    test    al, al
102    jz      strncat_copy
103    inc     rcx
104    test    ah, ah
105    jz      strncat_copy
106    inc     rcx
107    shr     rax, 16
108    test    al, al
109    jz      strncat_copy
110    inc     rcx
111    test    ah, ah
112    jz      strncat_copy
113    inc     rcx
114    shr     eax, 16
115    test    al, al
116    jz      strncat_copy
117    inc     rcx
118    test    ah, ah
119    jz      strncat_copy
120    inc     rcx
121    jmp     strncat_loop_begin
122
123strncat_copy:
124// align the SOURCE so we never page fault
125// dest pointer alignment not important
126    sub     rcx, rdx // combine pointers
127    test    dl, 7
128    jz      qword_loop_entrance
129
130copy_head_loop_begin:
131    mov     al, [rdx]
132    mov     [rdx+rcx], al
133    test    al, al
134    jz      byte_exit
135    inc     rdx
136    dec     r8
137    jz      byte_null_end
138    test    dl, 7
139    jnz     copy_head_loop_begin
140    jmp     qword_loop_entrance
141
142byte_null_end:
143    xor     al, al
144    mov     [rdx+rcx], al
145byte_exit:
146    mov     rax, r11
147    ret
148
149    nop
150
151qword_loop_begin:
152    mov     [rdx+rcx], rax
153    add     rdx, 8
154qword_loop_entrance:
155    mov     rax, [rdx]
156    sub     r8,  8
157    jbe     qword_loop_end
158    mov     r9, HEX(7efefefefefefeff)
159    add     r9, rax
160    mov     r10, rax
161    xor     r10, -1
162    xor     r10, r9
163    mov     r9, HEX(8101010101010100)
164    test    r10, r9
165    jz      qword_loop_begin
166
167qword_loop_end:
168    add     r8, 8
169    jz      strncat_exit_2
170
171    test    al, al
172    mov     [rdx+rcx], al
173    jz      strncat_exit
174    inc     rdx
175    dec     r8
176    jz      strncat_exit_2
177    test    ah, ah
178    mov     [rdx+rcx], ah
179    jz      strncat_exit
180    inc     rdx
181    dec     r8
182    jz      strncat_exit_2
183    shr     rax, 16
184    test    al, al
185    mov     [rdx+rcx], al
186    jz      strncat_exit
187    inc     rdx
188    dec     r8
189    jz      strncat_exit_2
190    test    ah, ah
191    mov     [rdx+rcx], ah
192    jz      strncat_exit
193    inc     rdx
194    dec     r8
195    jz      strncat_exit_2
196    shr     rax, 16
197    test    al, al
198    mov     [rdx+rcx], al
199    jz      strncat_exit
200    inc     rdx
201    dec     r8
202    jz      strncat_exit_2
203    test    ah, ah
204    mov     [rdx+rcx], ah
205    jz      strncat_exit
206    inc     rdx
207    dec     r8
208    jz      strncat_exit_2
209    shr     eax, 16
210    test    al, al
211    mov     [rdx+rcx], al
212    jz      strncat_exit
213    inc     rdx
214    dec     r8
215    jz      strncat_exit_2
216    test    ah, ah
217    mov     [rdx+rcx], ah
218    jz      strncat_exit
219    inc     rdx
220    dec     r8
221    jnz     qword_loop_entrance
222
223strncat_exit_2:
224    xor     al, al
225    mov     [rdx+rcx], al
226strncat_exit:
227    mov     rax, r11
228    ret
229
230LEAF_END strncat, _TEXT
231
232    end
233