/* NUL detection works on the principle that (X - 1) & (~X) & 0x80 (=>(X-1)&~(X|0x7f))isnon-zeroiffabyteiszero,and canbedoneinparallelacrosstheentireword.Afastercheck (X-1)&0x80iszerofornon-NULASCIIcharacters,butgives
false hits for characters 129..255. */
/* Since strings are short on average, we check the first 16 bytes ofthestringforaNULcharacter.Inordertodoanunalignedldp safelywehavetodoapagecrosscheckfirst.IfthereisaNUL bytewecalculatethelengthfromthe28-bytewordsusing conditionalselecttoreducebranchmispredictions(itisunlikely strlenwillberepeatedlycalledonstringswiththesamelength).
SYM_FUNC_START(__pi_strlen)
and tmp1, srcin, MIN_PAGE_SIZE - 1
mov zeroones, REP8_01
cmp tmp1, MIN_PAGE_SIZE - 16
b.gt L(page_cross)
ldp data1, data2, [srcin]
#ifdef __AARCH64EB__ /* For big-endian, carry propagation (if the final byte in the stringis0x01)meanswecannotusehas_nul1/2directly. Sinceweexpectstringstobesmallandearly-exit,
byte-swap the data now so has_null1/2 will be correct. */
rev data1, data1
rev data2, data2
#endif sub tmp1, data1, zeroones
orr tmp2, data1, REP8_7f sub tmp3, data2, zeroones
orr tmp4, data2, REP8_7f
bics has_nul1, tmp1, tmp2
bic has_nul2, tmp3, tmp4
ccmp has_nul2, 0, 0, eq
beq L(main_loop_entry)
/* Enter with C = has_nul1 == 0. */
csel has_nul1, has_nul1, has_nul2, cc
mov len, 8
rev has_nul1, has_nul1
clz tmp1, has_nul1
csel len, xzr, len, cc
add len, len, tmp1, lsr 3
ret
/* The inner loop processes 32 bytes per iteration and uses the fast NULcheck.Ifweencounternon-ASCIIcharacters,useasecond
loop with the accurate NUL check. */
.p2align 4
L(main_loop_entry):
bic src, srcin, 15 sub src, src, 16
L(main_loop):
ldp data1, data2, [src, 32]!
L(page_cross_entry): sub tmp1, data1, zeroones sub tmp3, data2, zeroones
orr tmp2, tmp1, tmp3
tst tmp2, zeroones, lsl 7
bne 1f
ldp data1, data2, [src, 16] sub tmp1, data1, zeroones sub tmp3, data2, zeroones
orr tmp2, tmp1, tmp3
tst tmp2, zeroones, lsl 7
beq L(main_loop)
add src, src, 16 1: /* The fast check failed, so do the slower, accurate NUL check. */
orr tmp2, data1, REP8_7f
orr tmp4, data2, REP8_7f
bics has_nul1, tmp1, tmp2
bic has_nul2, tmp3, tmp4
ccmp has_nul2, 0, 0, eq
beq L(nonascii_loop)
/* Enter with C = has_nul1 == 0. */
L(tail):
#ifdef __AARCH64EB__ /* For big-endian, carry propagation (if the final byte in the stringis0x01)meanswecannotusehas_nul1/2directly.The easiestwaytogetthecorrectbyteistobyte-swapthedata
and calculate the syndrome a second time. */
csel data1, data1, data2, cc
rev data1, data1 sub tmp1, data1, zeroones
orr tmp2, data1, REP8_7f
bic has_nul1, tmp1, tmp2
#else
csel has_nul1, has_nul1, has_nul2, cc
#endif sub len, src, srcin
rev has_nul1, has_nul1
add tmp2, len, 8
clz tmp1, has_nul1
csel len, len, tmp2, cc
add len, len, tmp1, lsr 3
ret
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.