IA64 strchr implementation.
[kopensolaris-gnu/glibc.git] / sysdeps / ia64 / strchr.S
1 /*
2  * Optimized version of the standard strchr() function
3  *
4  * Contributed by Dan Pop <Dan.Pop@cern.ch>
5  *
6  * Return: the address of the first occurence of chr in str or NULL
7  *
8  * Inputs:
9  *      in0:    str
10  *      in1:    chr
11  *
12  * A modified version of memchr.S, the search ends when the character is
13  * found or the terminating null character is encountered.
14  *
15  * This implementation assumes little endian mode.  For big endian mode,
16  * the instruction czx1.r should be replaced by czx1.l.
17  *
18  */
19
20 #include <sysdep.h>
21 #undef ret
22
23 #define saved_pfs       r14
24 #define saved_lc        r18
25 #define poschr          r19
26 #define pos0            r20
27 #define val1            r21
28 #define val2            r22
29 #define tmp             r24
30 #define chrx8           r25
31 #define loopcnt         r30
32
33 #define str             in0
34 #define chr             in1
35
36 ENTRY(strchr)
37         alloc saved_pfs = ar.pfs, 2, 0, 0, 0
38         mov     saved_lc = ar.lc        // save the loop counter
39         mov     ret0 = str      
40         and     tmp = 7, str            // tmp = str % 8
41         mux1    chrx8 = chr, @brcst
42         extr.u  chr = chr, 0, 8         // retain only the last byte
43         cmp.ne  p8, p0 = r0, r0         // clear p8
44         ;;
45         sub     loopcnt = 8, tmp        // loopcnt = 8 - tmp
46         cmp.eq  p6, p0 = tmp, r0
47 (p6)    br.cond.sptk    .str_aligned;;
48         adds    loopcnt = -1, loopcnt;;
49         mov     ar.lc = loopcnt
50 .l1:
51         ld1     val2 = [ret0], 1
52         ;;
53         cmp.eq  p6, p0 = val2, chr
54         cmp.eq  p7, p0 = val2, r0
55 (p6)    br.cond.spnt    .restore_and_exit
56 (p7)    br.cond.spnt    .notfound
57         br.cloop.sptk   .l1
58 .str_aligned:
59         ld8     val1 = [ret0], 8;;
60         nop.b   0
61         nop.b   0
62 .l2:    
63         ld8.s   val2 = [ret0], 8        // don't bomb out here
64         czx1.r  pos0 = val1     
65         xor     tmp = val1, chrx8       // if val1 contains chr, tmp will
66         ;;                              // contain a zero in its position
67         czx1.r  poschr = tmp
68         cmp.ne  p6, p0 = 8, pos0
69         ;;
70         cmp.ne  p7, p0 = 8, poschr
71 (p7)    br.cond.spnt .foundit
72 (p6)    br.cond.spnt .notfound
73         chk.s   val2, .recovery
74 .back:
75         mov     val1 = val2     
76         br.cond.dptk .l2
77 .foundit:
78 (p6)    cmp.lt  p8, p0 = pos0, poschr   // we found chr and null in the word
79 (p8)    br.cond.spnt .notfound          // null was found before chr
80         add     ret0 = ret0, poschr ;;
81         adds    ret0 = -15, ret0 ;;     // should be -16, but we decrement
82 .restore_and_exit:                      // ret0 in the next instruction
83         adds    ret0 = -1, ret0         // ret0 was pointing 1 char too far
84         mov     ar.pfs = saved_pfs      // restore the PFS
85         mov     ar.lc = saved_lc        // restore the loop counter
86         br.ret.sptk.many b0
87 .notfound:
88         mov     ret0 = r0               // return NULL if null was found
89         mov     ar.pfs = saved_pfs      // first
90         mov     ar.lc = saved_lc
91         br.ret.sptk.many b0
92 .recovery:
93         adds    ret0 = -8, ret0;;
94         ld8     val2 = [ret0], 8        // bomb out here
95         br.cond.sptk    .back
96 END(strchr)
97
98 weak_alias(strchr, index)