IA64 strlen implementation.
[kopensolaris-gnu/glibc.git] / sysdeps / ia64 / strlen.S
1 /*
2  * Optimized version of the standard strlen() function
3  *
4  * Contributed by Dan Pop <Dan.Pop@cern.ch>
5  *
6  * Return: the length of the input string
7  *
8  * Input:
9  *      in0:    str
10  *
11  * Look for the null character byte by byte, until we reach a word aligned
12  * address, then search word by word, using the czx instruction.  We're
13  * also doing one word of read ahead, which could cause problems if the
14  * null character is on the last word of a page and the next page is not
15  * mapped in the process address space.  Hence the use of the speculative
16  * load.
17  *
18  * This implementation assumes little endian mode.  For big endian mode,
19  * the instruction czx1.r should be replaced by czx1.l.
20  *
21  */
22
23 #include <sysdep.h>
24 #undef ret
25
26 #define saved_pfs       r14
27 #define saved_lc        r18
28 #define str             r19
29 #define pos0            r20
30 #define val1            r21
31 #define val2            r22
32 #define origadd         r23
33 #define tmp             r24
34 #define loopcnt         r30
35 #define len             ret0
36
37 ENTRY(strlen)
38         alloc saved_pfs = ar.pfs, 1, 0, 0, 0
39         mov     saved_lc = ar.lc        // save the loop counter
40         mov     str = in0       
41         mov     len = r0                // len = 0
42         and     tmp = 7, in0            // tmp = str % 8
43         ;;
44         sub     loopcnt = 8, tmp        // loopcnt = 8 - tmp
45         cmp.eq  p6, p0 = tmp, r0
46 (p6)    br.cond.sptk    str_aligned;;
47         adds    loopcnt = -1, loopcnt;;
48         mov     ar.lc = loopcnt
49 l1:
50         ld1     val2 = [str], 1
51         ;;
52         cmp.eq  p6, p0 = val2, r0
53 (p6)    br.cond.spnt    restore_and_exit
54         adds    len = 1, len
55         br.cloop.dptk   l1
56 str_aligned:
57         mov     origadd = str   // origadd = orig
58         ld8     val1 = [str], 8;;
59         nop.b   0
60         nop.b   0
61 l2:     ld8.s   val2 = [str], 8 // don't bomb out here
62         czx1.r  pos0 = val1     
63         ;;
64         cmp.ne  p6, p0 = 8, pos0
65 (p6)    br.cond.spnt foundit
66         chk.s   val2, recovery
67 back:
68         mov     val1 = val2     
69         br.cond.dptk l2
70 foundit:
71         sub     tmp = str, origadd      // tmp = crt address - orig
72         add     len = len, pos0;;
73         add     len = len, tmp;;
74         adds    len = -16, len
75 restore_and_exit:
76         mov ar.pfs = saved_pfs  // restore the PFS
77         mov ar.lc = saved_lc            // restore the loop counter
78         br.ret.sptk.many b0
79 recovery:
80         adds    str = -8, str;;
81         ld8     val2 = [str], 8 // bomb out here
82         br.cond.sptk    back
83 END(strlen)