]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libc/string/metag/memchr.S
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libc / string / metag / memchr.S
1 !    Copyright (C) 2013 Imagination Technologies Ltd.
2 !
3 !    Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
4
5         .text
6         .global _memchr
7         .type   _memchr,function
8 ! D0Ar6 src
9 ! D0Ar2 c
10 ! D1Ar3 n
11 _memchr:
12         CMP     D1Ar3, #0
13         BEQ     $Lexit_fail
14         !! convert c to unsigned char
15         AND     D0Ar2,D0Ar2,#0xff
16         MOV     D0Ar6, D1Ar1
17         MOV     D1Ar5, D0Ar6
18         !! test alignment
19         AND     D1Ar5, D1Ar5, #7
20         CMP     D1Ar5, #0
21         BNZ     $Lunaligned_loop
22         !! length must be greater than or equal to 8 for aligned loop
23         CMP     D1Ar3, #8
24         BGE     $Laligned_setup
25 $Lunaligned_loop:
26         !! get 1 char from s
27         GETB    D0Re0, [D0Ar6++]
28         !! increase alignment counter
29         ADD     D1Ar5, D1Ar5, #1
30         !! decrement n
31         SUB     D1Ar3, D1Ar3, #1
32         !! exit if we have a match
33         CMP     D0Re0, D0Ar2
34         BZ      $Lexit_success1
35         !! exit if we have hit the end of the string
36         CMP     D1Ar3, #0
37         BZ      $Lexit_fail
38         !! fall through if the buffer is aligned now
39         CMP     D1Ar5, #8
40         BNE     $Lunaligned_loop
41         !! fall through if there is more than 8 bytes left
42         CMP     D1Ar3, #8
43         BLT     $Lunaligned_loop
44 $Laligned_setup:
45         !! fill the c into 4 bytes
46         MOV     D0Ar4, D0Ar2
47         LSL     D0Ar4, D0Ar4, #8
48         ADD     D0Ar4, D0Ar4, D0Ar2
49         LSL     D0Ar4, D0Ar4, #8
50         ADD     D0Ar4, D0Ar4, D0Ar2
51         LSL     D0Ar4, D0Ar4, #8
52         ADD     D0Ar4, D0Ar4, D0Ar2
53         !! divide n by 8
54         MOV     D1Ar5, D1Ar3
55         LSR     D1Ar5, D1Ar5, #3
56 $Laligned_loop:
57         !! get 8 chars from s
58         GETL    D0Re0, D1Re0, [D0Ar6++]
59         !! decrement loop counter
60         SUB     D1Ar5, D1Ar5, #1
61         !! test first 4 chars
62         XOR     D0Re0, D0Re0, D0Ar4
63         !! test second 4 chars
64         MOV     D0Ar2, D1Re0
65         XOR     D1Re0, D0Ar2, D0Ar4
66         !! check for matches in the first 4 chars
67         MOV     D0Ar2, D0Re0
68         ADDT    D0Re0, D0Re0, #HI(0xfefefeff)
69         ADD     D0Re0, D0Re0, #LO(0xfefefeff)
70         XOR     D0Ar2, D0Ar2, #-1
71         AND     D0Re0, D0Re0, D0Ar2
72         ANDMT   D0Re0, D0Re0, #HI(0x80808080)
73         ANDMB   D0Re0, D0Re0, #LO(0x80808080)
74         CMP     D0Re0, #0
75         BNZ     $Lmatch_word1
76         !! check for matches in the second 4 chars
77         MOV     D1Ar1, D1Re0
78         ADDT    D1Re0, D1Re0, #HI(0xfefefeff)
79         ADD     D1Re0, D1Re0, #LO(0xfefefeff)
80         XOR     D1Ar1, D1Ar1, #-1
81         AND     D1Re0, D1Re0, D1Ar1
82         ANDMT   D1Re0, D1Re0, #HI(0x80808080)
83         ANDMB   D1Re0, D1Re0, #LO(0x80808080)
84         CMP     D1Re0, #0
85         BNZ     $Lmatch_word2
86         !! check if we have reached the end of the buffer
87         CMP     D1Ar5, #0
88         BNE     $Laligned_loop
89         !! exit if there are no chars left to check
90         AND     D1Ar3, D1Ar3, #7
91         CMP     D1Ar3, #0
92         BZ      $Lexit_fail
93         !! recover c
94         AND     D0Ar2, D0Ar4, #0xff
95 $Lbyte_loop:
96         !! get 1 char from s
97         GETB    D0Re0, [D0Ar6++]
98         !! decrement n
99         SUB     D1Ar3, D1Ar3, #1
100         !! exit if we have a match
101         CMP     D0Re0, D0Ar2
102         BZ      $Lexit_success1
103         !! fall through if we have run out of chars
104         CMP     D1Ar3, #0
105         BNE     $Lbyte_loop
106
107 $Lexit_fail:
108         MOV     D0Re0, #0
109         B       $Lend
110
111 $Lmatch_word1:
112         !! move the match word into D1Re0
113         MOV     D1Re0, D0Re0
114         !! roll back the buffer pointer by 4 chars
115         SUB     D0Ar6, D0Ar6, #4
116 $Lmatch_word2:
117         !! roll back the buffer pointer by 4 chars
118         SUB     D0Ar6, D0Ar6, #4
119         !! exit if lowest byte is 0
120         MOV     D1Ar1, D1Re0
121         AND     D1Ar1, D1Ar1, #0xff
122         CMP     D1Ar1, #0
123         BNE     $Lexit_success2
124         !! advance buffer pointer to the next char
125         ADD     D0Ar6, D0Ar6, #1
126         !! shift in the next lowest byte
127         LSR     D1Re0, D1Re0, #8
128         !! exit if lowest byte is 0
129         MOV     D1Ar1, D1Re0
130         AND     D1Ar1, D1Ar1, #0xff
131         CMP     D1Ar1, #0
132         BNE     $Lexit_success2
133         !! advance buffer pointer to the next char
134         ADD     D0Ar6, D0Ar6, #1
135         !! shift in the next lowest byte
136         LSR     D1Re0, D1Re0, #8
137         !! exit if lowest byte is 0
138         MOV     D1Ar1, D1Re0
139         AND     D1Ar1, D1Ar1, #0xff
140         CMP     D1Ar1, #0
141         BNE     $Lexit_success2
142         !! the match must be in the last byte, exit
143         ADD     D0Ar6, D0Ar6, #1
144         B       $Lexit_success2
145
146 $Lexit_success1:
147         SUB     D0Ar6, D0Ar6, #1
148 $Lexit_success2:
149         !! return the buffer pointer
150         MOV     D0Re0, D0Ar6
151 $Lend:
152         MOV     PC, D1RtP
153
154         .size _memchr,.-_memchr
155
156 libc_hidden_def(memchr)