diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/alpha/lib/memchr.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/alpha/lib/memchr.S')
-rw-r--r-- | arch/alpha/lib/memchr.S | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/arch/alpha/lib/memchr.S b/arch/alpha/lib/memchr.S new file mode 100644 index 000000000000..14427eeb555e --- /dev/null +++ b/arch/alpha/lib/memchr.S | |||
@@ -0,0 +1,164 @@ | |||
1 | /* Copyright (C) 1996 Free Software Foundation, Inc. | ||
2 | This file is part of the GNU C Library. | ||
3 | Contributed by David Mosberger (davidm@cs.arizona.edu). | ||
4 | |||
5 | The GNU C Library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public License as | ||
7 | published by the Free Software Foundation; either version 2 of the | ||
8 | License, or (at your option) any later version. | ||
9 | |||
10 | The GNU C Library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with the GNU C Library; see the file COPYING.LIB. If not, | ||
17 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. */ | ||
19 | |||
20 | /* Finds characters in a memory area. Optimized for the Alpha: | ||
21 | |||
22 | - memory accessed as aligned quadwords only | ||
23 | - uses cmpbge to compare 8 bytes in parallel | ||
24 | - does binary search to find 0 byte in last | ||
25 | quadword (HAKMEM needed 12 instructions to | ||
26 | do this instead of the 9 instructions that | ||
27 | binary search needs). | ||
28 | |||
29 | For correctness consider that: | ||
30 | |||
31 | - only minimum number of quadwords may be accessed | ||
32 | - the third argument is an unsigned long | ||
33 | */ | ||
34 | |||
35 | .set noreorder | ||
36 | .set noat | ||
37 | |||
38 | .globl memchr | ||
39 | .ent memchr | ||
40 | memchr: | ||
41 | .frame $30,0,$26,0 | ||
42 | .prologue 0 | ||
43 | |||
44 | # Hack -- if someone passes in (size_t)-1, hoping to just | ||
45 | # search til the end of the address space, we will overflow | ||
46 | # below when we find the address of the last byte. Given | ||
47 | # that we will never have a 56-bit address space, cropping | ||
48 | # the length is the easiest way to avoid trouble. | ||
49 | zap $18, 0x80, $5 #-e0 : | ||
50 | |||
51 | beq $18, $not_found # .. e1 : | ||
52 | ldq_u $1, 0($16) # e1 : load first quadword | ||
53 | insbl $17, 1, $2 # .. e0 : $2 = 000000000000ch00 | ||
54 | and $17, 0xff, $17 #-e0 : $17 = 00000000000000ch | ||
55 | cmpult $18, 9, $4 # .. e1 : | ||
56 | or $2, $17, $17 # e0 : $17 = 000000000000chch | ||
57 | lda $3, -1($31) # .. e1 : | ||
58 | sll $17, 16, $2 #-e0 : $2 = 00000000chch0000 | ||
59 | addq $16, $5, $5 # .. e1 : | ||
60 | or $2, $17, $17 # e1 : $17 = 00000000chchchch | ||
61 | unop # : | ||
62 | sll $17, 32, $2 #-e0 : $2 = chchchch00000000 | ||
63 | or $2, $17, $17 # e1 : $17 = chchchchchchchch | ||
64 | extql $1, $16, $7 # e0 : | ||
65 | beq $4, $first_quad # .. e1 : | ||
66 | |||
67 | ldq_u $6, -1($5) #-e1 : eight or less bytes to search | ||
68 | extqh $6, $16, $6 # .. e0 : | ||
69 | mov $16, $0 # e0 : | ||
70 | or $7, $6, $1 # .. e1 : $1 = quadword starting at $16 | ||
71 | |||
72 | # Deal with the case where at most 8 bytes remain to be searched | ||
73 | # in $1. E.g.: | ||
74 | # $18 = 6 | ||
75 | # $1 = ????c6c5c4c3c2c1 | ||
76 | $last_quad: | ||
77 | negq $18, $6 #-e0 : | ||
78 | xor $17, $1, $1 # .. e1 : | ||
79 | srl $3, $6, $6 # e0 : $6 = mask of $18 bits set | ||
80 | cmpbge $31, $1, $2 # .. e1 : | ||
81 | and $2, $6, $2 #-e0 : | ||
82 | beq $2, $not_found # .. e1 : | ||
83 | |||
84 | $found_it: | ||
85 | # Now, determine which byte matched: | ||
86 | negq $2, $3 # e0 : | ||
87 | and $2, $3, $2 # e1 : | ||
88 | |||
89 | and $2, 0x0f, $1 #-e0 : | ||
90 | addq $0, 4, $3 # .. e1 : | ||
91 | cmoveq $1, $3, $0 # e0 : | ||
92 | |||
93 | addq $0, 2, $3 # .. e1 : | ||
94 | and $2, 0x33, $1 #-e0 : | ||
95 | cmoveq $1, $3, $0 # .. e1 : | ||
96 | |||
97 | and $2, 0x55, $1 # e0 : | ||
98 | addq $0, 1, $3 # .. e1 : | ||
99 | cmoveq $1, $3, $0 #-e0 : | ||
100 | |||
101 | $done: ret # .. e1 : | ||
102 | |||
103 | # Deal with the case where $18 > 8 bytes remain to be | ||
104 | # searched. $16 may not be aligned. | ||
105 | .align 4 | ||
106 | $first_quad: | ||
107 | andnot $16, 0x7, $0 #-e1 : | ||
108 | insqh $3, $16, $2 # .. e0 : $2 = 0000ffffffffffff ($16<0:2> ff) | ||
109 | xor $1, $17, $1 # e0 : | ||
110 | or $1, $2, $1 # e1 : $1 = ====ffffffffffff | ||
111 | cmpbge $31, $1, $2 #-e0 : | ||
112 | bne $2, $found_it # .. e1 : | ||
113 | |||
114 | # At least one byte left to process. | ||
115 | |||
116 | ldq $1, 8($0) # e0 : | ||
117 | subq $5, 1, $18 # .. e1 : | ||
118 | addq $0, 8, $0 #-e0 : | ||
119 | |||
120 | # Make $18 point to last quad to be accessed (the | ||
121 | # last quad may or may not be partial). | ||
122 | |||
123 | andnot $18, 0x7, $18 # .. e1 : | ||
124 | cmpult $0, $18, $2 # e0 : | ||
125 | beq $2, $final # .. e1 : | ||
126 | |||
127 | # At least two quads remain to be accessed. | ||
128 | |||
129 | subq $18, $0, $4 #-e0 : $4 <- nr quads to be processed | ||
130 | and $4, 8, $4 # e1 : odd number of quads? | ||
131 | bne $4, $odd_quad_count # e1 : | ||
132 | |||
133 | # At least three quads remain to be accessed | ||
134 | |||
135 | mov $1, $4 # e0 : move prefetched value to correct reg | ||
136 | |||
137 | .align 4 | ||
138 | $unrolled_loop: | ||
139 | ldq $1, 8($0) #-e0 : prefetch $1 | ||
140 | xor $17, $4, $2 # .. e1 : | ||
141 | cmpbge $31, $2, $2 # e0 : | ||
142 | bne $2, $found_it # .. e1 : | ||
143 | |||
144 | addq $0, 8, $0 #-e0 : | ||
145 | $odd_quad_count: | ||
146 | xor $17, $1, $2 # .. e1 : | ||
147 | ldq $4, 8($0) # e0 : prefetch $4 | ||
148 | cmpbge $31, $2, $2 # .. e1 : | ||
149 | addq $0, 8, $6 #-e0 : | ||
150 | bne $2, $found_it # .. e1 : | ||
151 | |||
152 | cmpult $6, $18, $6 # e0 : | ||
153 | addq $0, 8, $0 # .. e1 : | ||
154 | bne $6, $unrolled_loop #-e1 : | ||
155 | |||
156 | mov $4, $1 # e0 : move prefetched value into $1 | ||
157 | $final: subq $5, $0, $18 # .. e1 : $18 <- number of bytes left to do | ||
158 | bne $18, $last_quad # e1 : | ||
159 | |||
160 | $not_found: | ||
161 | mov $31, $0 #-e0 : | ||
162 | ret # .. e1 : | ||
163 | |||
164 | .end memchr | ||