1 | /* Copy SRC to DEST returning the address of the terminating '\0' in DEST. |
2 | For Intel 80x86, x>=3. |
3 | Copyright (C) 1994-2024 Free Software Foundation, Inc. |
4 | This file is part of the GNU C Library. |
5 | |
6 | The GNU C Library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2.1 of the License, or (at your option) any later version. |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Lesser General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, see |
18 | <https://www.gnu.org/licenses/>. */ |
19 | |
20 | /* This function is defined neither in ANSI nor POSIX standards but is |
21 | also not invented here. */ |
22 | |
23 | #include <sysdep.h> |
24 | #include "asm-syntax.h" |
25 | |
26 | #define PARMS 4 /* no space for saved regs */ |
27 | #define RTN PARMS |
28 | #define DEST RTN |
29 | #define SRC DEST+4 |
30 | |
31 | .text |
32 | ENTRY (__stpcpy) |
33 | |
34 | movl DEST(%esp), %eax |
35 | movl SRC(%esp), %ecx |
36 | subl %eax, %ecx /* magic: reduce number of loop variants |
37 | to one using addressing mode */ |
38 | |
39 | /* Here we would like to write |
40 | |
41 | subl $4, %eax |
42 | ALIGN (4) |
43 | |
44 | but the assembler is too smart and optimizes for the shortest |
45 | form where the number only needs one byte. But if we could |
46 | have the long form we would not need the alignment. */ |
47 | |
48 | .byte 0x81, 0xe8 /* This is `subl $0x00000004, %eax' */ |
49 | .long 0x00000004 |
50 | |
51 | /* Four times unfolded loop with only one loop counter. This |
52 | is achieved by the use of index+base addressing mode. As the |
53 | loop counter we use the destination address because this is |
54 | also the result. */ |
55 | L(1): addl $4, %eax /* increment loop counter */ |
56 | |
57 | movb (%eax,%ecx), %dl /* load current char */ |
58 | movb %dl, (%eax) /* and store it */ |
59 | testb %dl, %dl /* was it NUL? */ |
60 | jz L(2) /* yes, then exit */ |
61 | |
62 | movb 1(%eax,%ecx), %dl /* load current char */ |
63 | movb %dl, 1(%eax) /* and store it */ |
64 | testb %dl, %dl /* was it NUL? */ |
65 | jz L(3) /* yes, then exit */ |
66 | |
67 | movb 2(%eax,%ecx), %dl /* load current char */ |
68 | movb %dl, 2(%eax) /* and store it */ |
69 | testb %dl, %dl /* was it NUL? */ |
70 | jz L(4) /* yes, then exit */ |
71 | |
72 | movb 3(%eax,%ecx), %dl /* load current char */ |
73 | movb %dl, 3(%eax) /* and store it */ |
74 | testb %dl, %dl /* was it NUL? */ |
75 | jnz L(1) /* no, then continue loop */ |
76 | |
77 | incl %eax /* correct loop counter */ |
78 | L(4): incl %eax |
79 | L(3): incl %eax |
80 | L(2): |
81 | |
82 | ret |
83 | END (__stpcpy) |
84 | |
85 | weak_alias (__stpcpy, stpcpy) |
86 | libc_hidden_def (__stpcpy) |
87 | libc_hidden_builtin_def (stpcpy) |
88 | |