1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <asm/regdef.h>
25
26 .set noat
27 .set noreorder
28
29 .text
30
31
32
33
34
35
36 .ent stxcpy_aligned
37 .align 3
38 stxcpy_aligned:
39 .frame sp, 0, t9
40 .prologue 0
41
42
43
44
45
46
47 lda t2, -1 # e1 : build a mask against false zero
48 mskqh t2, a1, t2 # e0 : detection in the src word
49 mskqh t1, a1, t3 # e0 :
50 ornot t1, t2, t2 # .. e1 :
51 mskql t0, a1, t0 # e0 : assemble the first output word
52 cmpbge zero, t2, t8 # .. e1 : bits set iff null found
53 or t0, t3, t1 # e0 :
54 bne t8, $a_eos # .. e1 :
55
56
57
58
59
60 $a_loop:
61 stq_u t1, 0(a0) # e0 :
62 addq a0, 8, a0 # .. e1 :
63 ldq_u t1, 0(a1) # e0 :
64 addq a1, 8, a1 # .. e1 :
65 cmpbge zero, t1, t8 # e0 (stall)
66 beq t8, $a_loop # .. e1 (zdb)
67
68
69
70
71
72 $a_eos:
73 negq t8, t6 # e0 : find low bit set
74 and t8, t6, t12 # e1 (stall)
75
76
77
78 and t12, 0x80, t6 # e0 :
79 bne t6, 1f # .. e1 (zdb)
80
81
82
83 ldq_u t0, 0(a0) # e0 :
84 subq t12, 1, t6 # .. e1 :
85 zapnot t1, t6, t1 # e0 : clear src bytes >= null
86 or t12, t6, t8 # .. e1 :
87 zap t0, t8, t0 # e0 : clear dst bytes <= null
88 or t0, t1, t1 # e1 :
89
90 1: stq_u t1, 0(a0) # e0 :
91 ret (t9) # .. e1 :
92
93 .end stxcpy_aligned
94
95 .align 3
96 .ent __stxcpy
97 .globl __stxcpy
98 __stxcpy:
99 .frame sp, 0, t9
100 .prologue 0
101
102
103 xor a0, a1, t0 # e0 :
104 unop # :
105 and t0, 7, t0 # e0 :
106 bne t0, $unaligned # .. e1 :
107
108
109 ldq_u t1, 0(a1) # e0 : load first src word
110 and a0, 7, t0 # .. e1 : take care not to load a word ...
111 addq a1, 8, a1 # e0 :
112 beq t0, stxcpy_aligned # .. e1 : ... if we wont need it
113 ldq_u t0, 0(a0) # e0 :
114 br stxcpy_aligned # .. e1 :
115
116
117
118
119
120
121 .align 3
122 $u_head:
123
124
125
126
127
128
129
130
131
132 ldq_u t2, 8(a1) # e0 :
133 addq a1, 8, a1 # .. e1 :
134
135 extql t1, a1, t1 # e0 :
136 extqh t2, a1, t4 # e0 :
137 mskql t0, a0, t0 # e0 :
138 or t1, t4, t1 # .. e1 :
139 mskqh t1, a0, t1 # e0 :
140 or t0, t1, t1 # e1 :
141
142 or t1, t6, t6 # e0 :
143 cmpbge zero, t6, t8 # .. e1 :
144 lda t6, -1 # e0 : for masking just below
145 bne t8, $u_final # .. e1 :
146
147 mskql t6, a1, t6 # e0 : mask out the bits we have
148 or t6, t2, t2 # e1 : already extracted before
149 cmpbge zero, t2, t8 # e0 : testing eos
150 bne t8, $u_late_head_exit # .. e1 (zdb)
151
152
153
154
155 stq_u t1, 0(a0) # e0 : store first output word
156 addq a0, 8, a0 # .. e1 :
157 extql t2, a1, t0 # e0 : position ho-bits of lo word
158 ldq_u t2, 8(a1) # .. e1 : read next high-order source word
159 addq a1, 8, a1 # e0 :
160 cmpbge zero, t2, t8 # .. e1 :
161 nop # e0 :
162 bne t8, $u_eos # .. e1 :
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 .align 3
178 $u_loop:
179 extqh t2, a1, t1 # e0 : extract high bits for current word
180 addq a1, 8, a1 # .. e1 :
181 extql t2, a1, t3 # e0 : extract low bits for next time
182 addq a0, 8, a0 # .. e1 :
183 or t0, t1, t1 # e0 : current dst word now complete
184 ldq_u t2, 0(a1) # .. e1 : load high word for next time
185 stq_u t1, -8(a0) # e0 : save the current word
186 mov t3, t0 # .. e1 :
187 cmpbge zero, t2, t8 # e0 : test new word for eos
188 beq t8, $u_loop # .. e1 :
189
190
191
192
193
194
195
196
197
198 $u_eos:
199 extqh t2, a1, t1 # e0 :
200 or t0, t1, t1 # e1 : first (partial) source word complete
201
202 cmpbge zero, t1, t8 # e0 : is the null in this first bit?
203 bne t8, $u_final # .. e1 (zdb)
204
205 $u_late_head_exit:
206 stq_u t1, 0(a0) # e0 : the null was in the high-order bits
207 addq a0, 8, a0 # .. e1 :
208 extql t2, a1, t1 # e0 :
209 cmpbge zero, t1, t8 # .. e1 :
210
211
212
213
214
215 $u_final:
216 negq t8, t6 # e0 : isolate low bit set
217 and t6, t8, t12 # e1 :
218
219 and t12, 0x80, t6 # e0 : avoid dest word load if we can
220 bne t6, 1f # .. e1 (zdb)
221
222 ldq_u t0, 0(a0) # e0 :
223 subq t12, 1, t6 # .. e1 :
224 or t6, t12, t8 # e0 :
225 zapnot t1, t6, t1 # .. e1 : kill source bytes >= null
226 zap t0, t8, t0 # e0 : kill dest bytes <= null
227 or t0, t1, t1 # e1 :
228
229 1: stq_u t1, 0(a0) # e0 :
230 ret (t9) # .. e1 :
231
232
233 .align 3
234 $unaligned:
235
236 ldq_u t1, 0(a1) # e0 : load first source word
237
238 and a0, 7, t4 # .. e1 : find dest misalignment
239 and a1, 7, t5 # e0 : find src misalignment
240
241
242
243
244 mov zero, t0 # .. e1 :
245 mov zero, t6 # e0 :
246 beq t4, 1f # .. e1 :
247 ldq_u t0, 0(a0) # e0 :
248 lda t6, -1 # .. e1 :
249 mskql t6, a0, t6 # e0 :
250 1:
251 subq a1, t4, a1 # .. e1 : sub dest misalignment from src addr
252
253
254
255
256 cmplt t4, t5, t12 # e0 :
257 beq t12, $u_head # .. e1 (zdb)
258
259 lda t2, -1 # e1 : mask out leading garbage in source
260 mskqh t2, t5, t2 # e0 :
261 nop # e0 :
262 ornot t1, t2, t3 # .. e1 :
263 cmpbge zero, t3, t8 # e0 : is there a zero?
264 beq t8, $u_head # .. e1 (zdb)
265
266
267
268
269
270
271 ldq_u t0, 0(a0) # e0 :
272
273 negq t8, t6 # .. e1 : build bitmask of bytes <= zero
274 and t6, t8, t12 # e0 :
275 and a1, 7, t5 # .. e1 :
276 subq t12, 1, t6 # e0 :
277 or t6, t12, t8 # e1 :
278 srl t12, t5, t12 # e0 : adjust final null return value
279
280 zapnot t2, t8, t2 # .. e1 : prepare source word; mirror changes
281 and t1, t2, t1 # e1 : to source validity mask
282 extql t2, a1, t2 # .. e0 :
283 extql t1, a1, t1 # e0 :
284
285 andnot t0, t2, t0 # .. e1 : zero place for source to reside
286 or t0, t1, t1 # e1 : and put it there
287 stq_u t1, 0(a0) # .. e0 :
288 ret (t9) # e1 :
289
290 .end __stxcpy