0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include <asm/regdef.h>
0033
0034 .set noat
0035 .set noreorder
0036
0037 .text
0038
0039
0040
0041
0042
0043
0044 .ent stxncpy_aligned
0045 .align 3
0046 stxncpy_aligned:
0047 .frame sp, 0, t9, 0
0048 .prologue 0
0049
0050
0051
0052
0053
0054
0055 lda t2, -1 # e1 : build a mask against false zero
0056 mskqh t2, a1, t2 # e0 : detection in the src word
0057 mskqh t1, a1, t3 # e0 :
0058 ornot t1, t2, t2 # .. e1 :
0059 mskql t0, a1, t0 # e0 : assemble the first output word
0060 cmpbge zero, t2, t8 # .. e1 : bits set iff null found
0061 or t0, t3, t0 # e0 :
0062 beq a2, $a_eoc # .. e1 :
0063 bne t8, $a_eos # .. e1 :
0064
0065
0066
0067
0068 $a_loop:
0069 stq_u t0, 0(a0) # e0 :
0070 addq a0, 8, a0 # .. e1 :
0071 ldq_u t0, 0(a1) # e0 :
0072 addq a1, 8, a1 # .. e1 :
0073 subq a2, 1, a2 # e0 :
0074 cmpbge zero, t0, t8 # .. e1 (stall)
0075 beq a2, $a_eoc # e1 :
0076 beq t8, $a_loop # e1 :
0077
0078
0079
0080
0081
0082
0083
0084
0085 $a_eos:
0086 negq t8, t12 # e0 : find low bit set
0087 and t8, t12, t12 # e1 (stall)
0088
0089
0090
0091 and t12, 0x80, t6 # e0 :
0092 bne t6, 1f # .. e1 (zdb)
0093
0094
0095
0096 ldq_u t1, 0(a0) # e0 :
0097 subq t12, 1, t6 # .. e1 :
0098 or t12, t6, t8 # e0 :
0099 unop #
0100 zapnot t0, t8, t0 # e0 : clear src bytes > null
0101 zap t1, t8, t1 # .. e1 : clear dst bytes <= null
0102 or t0, t1, t0 # e1 :
0103
0104 1: stq_u t0, 0(a0) # e0 :
0105 ret (t9) # e1 :
0106
0107
0108 $a_eoc:
0109 or t10, t8, t8
0110 br $a_eos
0111
0112 .end stxncpy_aligned
0113
0114 .align 3
0115 .ent __stxncpy
0116 .globl __stxncpy
0117 __stxncpy:
0118 .frame sp, 0, t9, 0
0119 .prologue 0
0120
0121
0122 xor a0, a1, t1 # e0 :
0123 and a0, 7, t0 # .. e1 : find dest misalignment
0124 and t1, 7, t1 # e0 :
0125 addq a2, t0, a2 # .. e1 : bias count by dest misalignment
0126 subq a2, 1, a2 # e0 :
0127 and a2, 7, t2 # e1 :
0128 srl a2, 3, a2 # e0 : a2 = loop counter = (count - 1)/8
0129 addq zero, 1, t10 # .. e1 :
0130 sll t10, t2, t10 # e0 : t10 = bitmask of last count byte
0131 bne t1, $unaligned # .. e1 :
0132
0133
0134
0135 ldq_u t1, 0(a1) # e0 : load first src word
0136 addq a1, 8, a1 # .. e1 :
0137
0138 beq t0, stxncpy_aligned # avoid loading dest word if not needed
0139 ldq_u t0, 0(a0) # e0 :
0140 br stxncpy_aligned # .. e1 :
0141
0142
0143
0144
0145
0146
0147 .align 3
0148 $u_head:
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 ldq_u t2, 8(a1) # e0 : load second src word
0159 addq a1, 8, a1 # .. e1 :
0160 mskql t0, a0, t0 # e0 : mask trailing garbage in dst
0161 extqh t2, a1, t4 # e0 :
0162 or t1, t4, t1 # e1 : first aligned src word complete
0163 mskqh t1, a0, t1 # e0 : mask leading garbage in src
0164 or t0, t1, t0 # e0 : first output word complete
0165 or t0, t6, t6 # e1 : mask original data for zero test
0166 cmpbge zero, t6, t8 # e0 :
0167 beq a2, $u_eocfin # .. e1 :
0168 lda t6, -1 # e0 :
0169 bne t8, $u_final # .. e1 :
0170
0171 mskql t6, a1, t6 # e0 : mask out bits already seen
0172 nop # .. e1 :
0173 stq_u t0, 0(a0) # e0 : store first output word
0174 or t6, t2, t2 # .. e1 :
0175 cmpbge zero, t2, t8 # e0 : find nulls in second partial
0176 addq a0, 8, a0 # .. e1 :
0177 subq a2, 1, a2 # e0 :
0178 bne t8, $u_late_head_exit # .. e1 :
0179
0180
0181
0182
0183 extql t2, a1, t1 # e0 : position hi-bits of lo word
0184 beq a2, $u_eoc # .. e1 :
0185 ldq_u t2, 8(a1) # e0 : read next high-order source word
0186 addq a1, 8, a1 # .. e1 :
0187 extqh t2, a1, t0 # e0 : position lo-bits of hi word (stall)
0188 cmpbge zero, t2, t8 # .. e1 :
0189 nop # e0 :
0190 bne t8, $u_eos # .. e1 :
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 .align 3
0207 $u_loop:
0208 or t0, t1, t0 # e0 : current dst word now complete
0209 subq a2, 1, a2 # .. e1 : decrement word count
0210 stq_u t0, 0(a0) # e0 : save the current word
0211 addq a0, 8, a0 # .. e1 :
0212 extql t2, a1, t1 # e0 : extract high bits for next time
0213 beq a2, $u_eoc # .. e1 :
0214 ldq_u t2, 8(a1) # e0 : load high word for next time
0215 addq a1, 8, a1 # .. e1 :
0216 nop # e0 :
0217 cmpbge zero, t2, t8 # e1 : test new word for eos (stall)
0218 extqh t2, a1, t0 # e0 : extract low bits for current word
0219 beq t8, $u_loop # .. e1 :
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230 $u_eos:
0231 or t0, t1, t0 # e0 : first (partial) source word complete
0232 nop # .. e1 :
0233 cmpbge zero, t0, t8 # e0 : is the null in this first bit?
0234 bne t8, $u_final # .. e1 (zdb)
0235
0236 stq_u t0, 0(a0) # e0 : the null was in the high-order bits
0237 addq a0, 8, a0 # .. e1 :
0238 subq a2, 1, a2 # e1 :
0239
0240 $u_late_head_exit:
0241 extql t2, a1, t0 # .. e0 :
0242 cmpbge zero, t0, t8 # e0 :
0243 or t8, t10, t6 # e1 :
0244 cmoveq a2, t6, t8 # e0 :
0245 nop # .. e1 :
0246
0247
0248
0249
0250
0251 $u_final:
0252 negq t8, t6 # e0 : isolate low bit set
0253 and t6, t8, t12 # e1 :
0254
0255 and t12, 0x80, t6 # e0 : avoid dest word load if we can
0256 bne t6, 1f # .. e1 (zdb)
0257
0258 ldq_u t1, 0(a0) # e0 :
0259 subq t12, 1, t6 # .. e1 :
0260 or t6, t12, t8 # e0 :
0261 zapnot t0, t8, t0 # .. e1 : kill source bytes > null
0262 zap t1, t8, t1 # e0 : kill dest bytes <= null
0263 or t0, t1, t0 # e1 :
0264
0265 1: stq_u t0, 0(a0) # e0 :
0266 ret (t9) # .. e1 :
0267
0268
0269
0270
0271 $u_eoc:
0272 and a1, 7, t6 # e1 :
0273 sll t10, t6, t6 # e0 :
0274 and t6, 0xff, t6 # e0 :
0275 bne t6, 1f # .. e1 :
0276
0277 ldq_u t2, 8(a1) # e0 : load final src word
0278 nop # .. e1 :
0279 extqh t2, a1, t0 # e0 : extract low bits for last word
0280 or t1, t0, t1 # e1 :
0281
0282 1: cmpbge zero, t1, t8
0283 mov t1, t0
0284
0285 $u_eocfin: # end-of-count, final word
0286 or t10, t8, t8
0287 br $u_final
0288
0289
0290 .align 3
0291 $unaligned:
0292
0293 ldq_u t1, 0(a1) # e0 : load first source word
0294
0295 and a0, 7, t4 # .. e1 : find dest misalignment
0296 and a1, 7, t5 # e0 : find src misalignment
0297
0298
0299
0300
0301 mov zero, t0 # .. e1 :
0302 mov zero, t6 # e0 :
0303 beq t4, 1f # .. e1 :
0304 ldq_u t0, 0(a0) # e0 :
0305 lda t6, -1 # .. e1 :
0306 mskql t6, a0, t6 # e0 :
0307 subq a1, t4, a1 # .. e1 : sub dest misalignment from src addr
0308
0309
0310
0311
0312 1: cmplt t4, t5, t12 # e1 :
0313 extql t1, a1, t1 # .. e0 : shift src into place
0314 lda t2, -1 # e0 : for creating masks later
0315 beq t12, $u_head # .. e1 :
0316
0317 extql t2, a1, t2 # e0 :
0318 cmpbge zero, t1, t8 # .. e1 : is there a zero?
0319 andnot t2, t6, t2 # e0 : dest mask for a single word copy
0320 or t8, t10, t5 # .. e1 : test for end-of-count too
0321 cmpbge zero, t2, t3 # e0 :
0322 cmoveq a2, t5, t8 # .. e1 :
0323 andnot t8, t3, t8 # e0 :
0324 beq t8, $u_head # .. e1 (zdb)
0325
0326
0327
0328
0329
0330
0331 ldq_u t0, 0(a0) # e0 :
0332 negq t8, t6 # .. e1 : build bitmask of bytes <= zero
0333 mskqh t1, t4, t1 # e0 :
0334 and t6, t8, t12 # .. e1 :
0335 subq t12, 1, t6 # e0 :
0336 or t6, t12, t8 # e1 :
0337
0338 zapnot t2, t8, t2 # e0 : prepare source word; mirror changes
0339 zapnot t1, t8, t1 # .. e1 : to source validity mask
0340
0341 andnot t0, t2, t0 # e0 : zero place for source to reside
0342 or t0, t1, t0 # e1 : and put it there
0343 stq_u t0, 0(a0) # e0 :
0344 ret (t9) # .. e1 :
0345
0346 .end __stxncpy