/* 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 */
/* On entry to this basic block: t0==thefirstdestinationwordformaskingbackin
t1 == the first source word. */
/* Create the 1st output word and detect 0's in the 1st input word. */ lda t2, -1 # e1 : build a mask against false zero
mskqh t2, a1, t2 # e0 : detection in the src word
mskqh t1, a1, t3 # e0 :
ornot t1, t2, t2 # .. e1 :
mskql t0, a1, t0 # e0 : assemble the first output word
cmpbge zero, t2, t8 # .. e1 : bits set iff null found
or t0, t3, t1 # e0 :
bne t8, $a_eos # .. e1 :
/* On entry to this basic block: t0==thefirstdestinationwordformaskingbackin
t1 == a source word not containing a null. */
/* Take care of the final (partial) word store. Onentrytothisbasicblockwehave: t1==thesourcewordcontainingthenull
t8 == the cmpbge mask that found it. */
$a_eos:
negq t8, t6 # e0 : find low bit set
and t8, t6, t12 # e1 (stall)
/* For the sake of the cache, don't read a destination word
if we're not going to need it. */
and t12, 0x80, t6 # e0 :
bne t6, 1f # .. e1 (zdb)
/* We're doing a partial word store and so need to combine
our source and original destination words. */
ldq_u t0, 0(a0) # e0 :
subq t12, 1, t6 # .. e1 :
zapnot t1, t6, t1 # e0 : clear src bytes >= null
or t12, t6, t8 # .. e1 :
zap t0, t8, t0 # e0 : clear dst bytes <= null
or t0, t1, t1 # e1 :
/* We are co-aligned; take care of a partial first word. */
ldq_u t1, 0(a1) # e0 : load first src word
and a0, 7, t0 # .. e1 : take care not to load a word ...
addq a1, 8, a1 # e0 :
beq t0, stxcpy_aligned # .. e1 : ... if we wont need it
ldq_u t0, 0(a0) # e0 :
br stxcpy_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,formaskingbackin,ifneededelse0 t1==thelowbitsofthefirstsourceword
t6 == bytemask that is -1 in dest word bytes */
mskql t6, a1, t6 # e0 : mask out the bits we have
or t6, t2, t2 # e1 : already extracted before
cmpbge zero, t2, t8 # e0 : testing eos
bne t8, $u_late_head_exit # .. e1 (zdb)
/* Finally, we've got all the stupid leading edge cases taken care
of and we can set up to enter the main loop. */
stq_u t1, 0(a0) # e0 : store first output word
addq a0, 8, a0 # .. e1 :
extql t2, a1, t0 # e0 : position ho-bits of loword
ldq_u t2, 8(a1) # .. e1 : read next high-order source word
addq a1, 8, a1 # e0 :
cmpbge zero, t2, t8 # .. e1 :
nop # e0 :
bne t8, $u_eos # .. e1 :
/* 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:
extqh t2, a1, t1 # e0 : extract high bits for current word
addq a1, 8, a1 # .. e1 :
extql t2, a1, t3 # e0 : extract low bits for next time
addq a0, 8, a0 # .. e1 :
or t0, t1, t1 # e0 : current dst word now complete
ldq_u t2, 0(a1) # .. e1 : load high word for next time
stq_u t1, -8(a0) # e0 : save the current word
mov t3, t0 # .. e1 :
cmpbge zero, t2, t8 # e0 : test new word for eos
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==theshiftedhigh-orderbitsfromtheprevioussourceword
t2 == the unshifted current source word. */
$u_eos:
extqh t2, a1, t1 # e0 :
or t0, t1, t1 # e1 : first (partial) source word complete
cmpbge zero, t1, t8 # e0 : is the null in this first bit?
bne t8, $u_final # .. e1 (zdb)
$u_late_head_exit:
stq_u t1, 0(a0) # e0 : the null was in the high-order bits
addq a0, 8, a0 # .. e1 :
extql t2, a1, t1 # e0 :
cmpbge zero, t1, t8 # .. e1 :
/* Take care of a final (probably partial) result word. Onentrytothisbasicblock: t1==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)
lda t2, -1 # e1 : mask out leading garbage in source
mskqh t2, t5, t2 # e0 :
nop # e0 :
ornot t1, t2, t3 # .. e1 :
cmpbge zero, t3, t8 # e0 : is there a zero?
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.) */
ldq_u t0, 0(a0) # e0 :
negq t8, t6 # .. e1 : build bitmask of bytes <= zero
and t6, t8, t12 # e0 :
and a1, 7, t5 # .. e1 :
subq t12, 1, t6 # e0 :
or t6, t12, t8 # e1 : srl t12, t5, t12 # e0 : adjust final null return value
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.