/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that doesn'tlikeputtingtheentrypointforaproceduresomewhereinthe middleoftheproceduredescriptor.Workaroundthisbyputtingthe
aligned copy in its own procedure descriptor */
/* We are co-aligned; take care of a partial first word. */
ldq_u t1, 0(a1) # e0 : load first src word
addq a1, 8, a1 # .. e1 :
beq t0, stxncpy_aligned # avoid loading dest word if not needed
ldq_u t0, 0(a0) # e0 :
br stxncpy_aligned # .. e1 :
/* The source and destination are not co-aligned. Align the destination andcope.Wehavetobeverycarefulaboutnotreadingtoomuchand
causing a SEGV. */
.align3
$u_head: /* We know just enough now to be able to assemble the first fullsourceword.Wecanstillfindazeroattheendofit thatpreventsusfromoutputtingthewholething.
Onentrytothisbasicblock: t0==thefirstdestword,unmasked t1==theshiftedlowbitsofthefirstsourceword
t6 == bytemask that is -1 in dest word bytes */
ldq_u t2, 8(a1) # e0 : load second src word
addq a1, 8, a1 # .. e1 :
mskql t0, a0, t0 # e0 : mask trailing garbage in dst
extqh t2, a1, t4 # e0 :
or t1, t4, t1 # e1 : first aligned src word complete
mskqh t1, a0, t1 # e0 : mask leading garbage in src
or t0, t1, t0 # e0 : first output word complete
or t0, t6, t6 # e1 : mask original data for zero test
cmpbge zero, t6, t8 # e0 :
beq a2, $u_eocfin # .. e1 : lda t6, -1 # e0 :
bne t8, $u_final # .. e1 :
mskql t6, a1, t6 # e0 : mask out bits already seen
nop # .. e1 :
stq_u t0, 0(a0) # e0 : store first output word
or t6, t2, t2 # .. e1 :
cmpbge zero, t2, t8 # e0 : find nulls in second partial
addq a0, 8, a0 # .. e1 :
subq a2, 1, a2 # e0 :
bne t8, $u_late_head_exit # .. e1 :
/* Finally, we've got all the stupid leading edge cases taken care
of and we can set up to enter the main loop. */
/* Unaligned copy main loop. In order to avoid reading too much, theloopisstructuredtodetectzerosinalignedsourcewords. Thishas,unfortunately,effectivelypulledhalfofaloop iterationoutintotheheadandhalfintothetail,butitdoes preventnastinessfromaccumulatingintheverythingwewant torunasfastaspossible.
We further know that t2 does not contain a null terminator. */
.align3
$u_loop:
or t0, t1, t0 # e0 : current dst word now complete
subq a2, 1, a2 # .. e1 : decrement word count
stq_u t0, 0(a0) # e0 : save the current word
addq a0, 8, a0 # .. e1 :
extql t2, a1, t1 # e0 : extract high bits for next time
beq a2, $u_eoc # .. e1 :
ldq_u t2, 8(a1) # e0 : load high word for next time
addq a1, 8, a1 # .. e1 :
nop # e0 :
cmpbge zero, t2, t8 # e1 : test new word for eos (stall)
extqh t2, a1, t0 # e0 : extract low bits for current word
beq t8, $u_loop # .. e1 :
/* We've found a zero somewhere in the source word we just read. Ifitresidesinthelowerhalf,wehaveone(probablypartial) wordtowriteout,andifitresidesintheupperhalf,we haveonefullandonepartialwordlefttowriteout.
Onentrytothisbasicblock: t0==theshiftedlow-orderbitsfromthecurrentsourceword t1==theshiftedhigh-orderbitsfromtheprevioussourceword
t2 == the unshifted current source word. */
$u_eos:
or t0, t1, t0 # e0 : first (partial) source word complete
nop # .. e1 :
cmpbge zero, t0, t8 # e0 : is the null in this first bit?
bne t8, $u_final # .. e1 (zdb)
stq_u t0, 0(a0) # e0 : the null was in the high-order bits
addq a0, 8, a0 # .. e1 :
subq a2, 1, a2 # e1 :
/* Take care of a final (probably partial) result word. Onentrytothisbasicblock: t0==assembledsourceword
t8 == cmpbge mask that found the null. */
$u_final:
negq t8, t6 # e0 : isolate low bit set
and t6, t8, t12 # e1 :
and t12, 0x80, t6 # e0 : avoid dest word load if we can
bne t6, 1f # .. e1 (zdb)
/* Got to end-of-count before end of string. Onentrytothisbasicblock:
t1 == the shifted high-order bits from the previous source word */
$u_eoc:
and a1, 7, t6 # e1 : sll t10, t6, t6 # e0 :
and t6, 0xff, t6 # e0 :
bne t6, 1f # .. e1 :
ldq_u t2, 8(a1) # e0 : load final src word
nop # .. e1 :
extqh t2, a1, t0 # e0 : extract low bits for last word
or t1, t0, t1 # e1 :
1: cmpbge zero, t1, t8
mov t1, t0
$u_eocfin: # end-of-count, final word
or t10, t8, t8
br $u_final
/* If source misalignment is larger than dest misalignment, we need
extra startup checks to avoid SEGV. */
1: cmplt t4, t5, t12 # e1 :
extql t1, a1, t1 # .. e0 : shift src into place lda t2, -1 # e0 : for creating masks later
beq t12, $u_head # .. e1 :
extql t2, a1, t2 # e0 :
cmpbge zero, t1, t8 # .. e1 : is there a zero?
andnot t2, t6, t2 # e0 : dest mask for a single word copy
or t8, t10, t5 # .. e1 : test for end-of-count too
cmpbge zero, t2, t3 # e0 :
cmoveq a2, t5, t8 # .. e1 :
andnot t8, t3, t8 # e0 :
beq t8, $u_head # .. e1 (zdb)
/* At this point we've found a zero in the first partial word of thesource.Weneedtoisolatethevalidsourcedataandmask itintotheoriginaldestinationdata.(Incidentally,weknow
that we'll need at least one byte of that original dest word.) */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.