Call strnlen() when determining the
[kopensolaris-gnu/glibc.git] / sysdeps / ia64 / strncpy.S
1 /* Optimized version of the standard strncpy() function.
2    This file is part of the GNU C Library.
3    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4    Contributed by Dan Pop <Dan.Pop@cern.ch>.
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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 /* Return: dest
22
23    Inputs:
24         in0:    dest
25         in1:    src
26         in2:    char count
27
28    If n >= 24, do a memcpy(dest, src, min(strnlen(src, n)+1, n)), followed by a
29    memset(dest + strlen(src, n), 0, n - strlen(src, n) - 1) if necessary.
30
31    Otherwise, copy characters one by one and fill with nulls if necessary.  */
32
33 #include <sysdep.h>
34 #undef ret
35
36 #define saved_b0        loc0
37 #define saved_pfs       loc1
38 #define saved_pr        loc2
39 #define saved_lc        loc3
40 #define tmp             loc4
41 #define len             loc5
42
43 #define dest            in0
44 #define src             in1
45 #define n               in2
46
47 #define rc              ret0
48
49 ENTRY(strncpy)
50         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3)
51         alloc   saved_pfs = ar.pfs, 3, 6, 3, 0
52         mov     saved_b0 = b0
53         .save pr, saved_pr
54         mov     saved_pr = pr
55         .save ar.lc, saved_lc
56         mov     saved_lc = ar.lc
57         .body
58         cmp.gtu p6, p0 = 24, n
59 (p6)    br.cond.spnt .cpyfew
60         mov     out0 = src
61         mov     out1 = n
62         mov     tmp = gp
63         br.call.sptk.many b0 = strnlen# ;;      // rc = strnlen(src, n);
64         add     len = 1, rc                     // include the null in len
65         mov     gp = tmp
66         mov     out0 = dest ;;
67         cmp.ltu p4, p5 = len, n
68         mov     out1 = src ;;
69 (p4)    mov     out2 = len
70 (p5)    mov     out2 = n
71         br.call.sptk.many b0 = memcpy# ;;       // memcpy(dest, src, min(len, n));
72         mov     gp = tmp
73 (p4)    add     out0 = dest, len
74 (p4)    mov     out1 = r0
75 (p4)    sub     out2 = n, len
76 (p4)    br.call.sptk.many b0 = memset# ;;       // fill the rest with nulls
77 (p4)    mov     gp = tmp
78         mov     rc = dest
79         mov     b0 = saved_b0
80         mov     ar.pfs = saved_pfs
81         mov     pr = saved_pr, -1
82         br.ret.sptk.many b0
83 .cpyfew:
84         mov     rc = dest
85         cmp.eq  p6, p0 = n, r0          
86         adds    n = -1, n
87 (p6)    br.cond.spnt .restore_and_exit ;;       // do nothing if n == 0
88         mov     ar.lc = n
89         cmp.eq  p6, p0 = r0, r0 ;;              // set p6
90 .loop:
91 (p6)    ld1     tmp = [src],1 
92         ;;
93         st1     [dest] = tmp, 1
94 (p6)    cmp.ne  p6, p0 = tmp, r0        // clear p6 after encountering the
95         br.cloop.dptk .loop ;;          // null character in src
96 .restore_and_exit:
97         mov     ar.lc = saved_lc
98         mov     ar.pfs = saved_pfs
99         br.ret.sptk.many b0
100 END(strncpy)