diff options
-rw-r--r-- | sysdeps/aarch64/memset.S | 221 |
1 files changed, 125 insertions, 96 deletions
diff --git a/sysdeps/aarch64/memset.S b/sysdeps/aarch64/memset.S index 523406d3c8..2e15551006 100644 --- a/sysdeps/aarch64/memset.S +++ b/sysdeps/aarch64/memset.S @@ -26,7 +26,6 @@ #define dstin x0 #define dstin_w w0 -#define val x1 #define valw w1 #define count x2 #define tmp1 x3 @@ -87,28 +86,27 @@ memset: .type memset_zva_64, %function memset_zva_64: CALL_MCOUNT - and valw, valw, #255 - cmp count, #256 - ccmp valw, #0, #0, hs /* hs ? cmp val,0 : !z */ + tst valw, #255 b.ne L(nz_or_small) - stp xzr, xzr, [dstin] /* first 16 aligned 1. */ + cmp count, #256 + dup v16.16b, valw + add dstend, dstin, count + b.lo L(le_255) + + str q16, [dstin] /* first 16 aligned 1. */ and tmp2, dstin, #-16 and dst, dstin, #-64 - stp xzr, xzr, [tmp2, #16] /* first 64 aligned 16. */ - add dstend, dstin, count + stp q16, q16, [tmp2, #16] /* first 64 aligned 16. */ add dst, dst, #64 - stp xzr, xzr, [tmp2, #32] + stp q16, q16, [tmp2, #48] sub count, dstend, dst /* recompute for misalign */ add tmp1, dst, #64 - stp xzr, xzr, [tmp2, #48] sub count, count, #128 /* pre-bias */ - stp xzr, xzr, [tmp2, #64] - .p2align 6,,24 0: dc zva, dst subs count, count, #128 @@ -126,7 +124,26 @@ memset_zva_64: /* For larger zva sizes, a simple loop ought to suffice. */ /* ??? Needs performance testing, when such hardware becomes available. */ -.macro do_zva len +.macro do_zvas len + .p2align 4 + .type memset_zva_\len, %function +memset_zva_\len: + CALL_MCOUNT + tst valw, #255 + b.ne L(nz_or_small) + + cmp count, #256 + dup v16.16b, valw + add dstend, dstin, count + b.lo L(le_255) + + mov zva_len, #\len + b memset_zva_n + + .size memset_zva_\len, . - memset_zva_\len +.endm + +.macro do_zval len .p2align 4 .type memset_zva_\len, %function memset_zva_\len: @@ -138,23 +155,22 @@ memset_zva_\len: add dstend, dstin, count mov zva_len, #\len - mov zva_mask, #\len-1 b memset_zva_n .size memset_zva_\len, . - memset_zva_\len .endm - do_zva 128 // 5 - do_zva 256 // 6 - do_zva 512 // 7 - do_zva 1024 // 8 - do_zva 2048 // 9 - do_zva 4096 // 10 - do_zva 8192 // 11 - do_zva 16384 // 12 - do_zva 32768 // 13 - do_zva 65536 // 14 - do_zva 131072 // 15 + do_zvas 128 // 5 + do_zvas 256 // 6 + do_zval 512 // 7 + do_zval 1024 // 8 + do_zval 2048 // 9 + do_zval 4096 // 10 + do_zval 8192 // 11 + do_zval 16384 // 12 + do_zval 32768 // 13 + do_zval 65536 // 14 + do_zval 131072 // 15 .p2align 6 #else @@ -163,21 +179,26 @@ memset_zva_\len: .p2align 6 .type memset, %function memset: - and valw, valw, #255 - cmp count, #256 - ccmp valw, #0, #0, hs /* hs ? cmp val,0 : !z */ + tst valw, #255 b.ne L(nz_or_small) + cmp count, #256 + dup v16.16b, valw + add dstend, dstin, count + b.lo L(le_255) + mrs tmp1, dczid_el0 - tbnz tmp1, #4, L(nz_or_small) + mov zva_len, #4 + tst tmp1w, #16 /* dc disabled? */ and tmp1w, tmp1w, #15 - mov zva_len, #4 - add dstend, dstin, count + + ccmp tmp1w, #4, #0, eq /* eq ? cmp len,64 : !c */ lsl zva_len, zva_len, tmp1w - cmp count, zva_len_x - sub zva_mask, zva_len, #1 - b.lo L(ge_64) + + ccmp count, zva_len_x, #0, hs /* hs ? cmp count,len : !c */ + + b.lo L(ge_256) /* disabled || len<64 || count<len */ /* Fall through into memset_zva_n. */ .size memset, . - memset @@ -188,8 +209,9 @@ memset: .type memset_zva_n, %function memset_zva_n: - stp xzr, xzr, [dstin] /* first 16 aligned 1. */ + stp q16, q16, [dstin] /* first 32 aligned 1. */ neg tmp1w, dstin_w + sub zva_mask, zva_len, #1 sub count, count, zva_len_x /* pre-bias */ mov dst, dstin ands tmp1w, tmp1w, zva_mask @@ -206,16 +228,14 @@ memset_zva_n: RET .p2align 4 -3: and tmp2, dstin, #-16 +3: and tmp2, dstin, #-32 sub count, count, tmp1 /* account for misalign */ add dst, dstin, tmp1 .p2align 6,,24 -4: stp xzr, xzr, [tmp2, #16] - stp xzr, xzr, [tmp2, #32] +4: stp q16, q16, [tmp2, #32] subs tmp1w, tmp1w, #64 - stp xzr, xzr, [tmp2, #48] - stp xzr, xzr, [tmp2, #64]! + stp q16, q16, [tmp2, #64]! b.hi 4b b 2b @@ -228,83 +248,92 @@ memset_zva_n: .type memset_nozva, %function memset_nozva: CALL_MCOUNT - and valw, valw, #255 L(nz_or_small): - orr valw, valw, valw, lsl #8 /* replicate the byte */ + dup v16.16b, valw + cmp count, #256 + add dstend, dstin, count + b.hs L(ge_256) + + /* Small data -- original count is less than 256 bytes. */ +L(le_255): + cmp count, #32 + b.lo L(le_31) + + stp q16, q16, [dstin] cmp count, #64 - orr valw, valw, valw, lsl #16 - add dstend, dstin, count /* remember end of buffer */ - orr val, val, val, lsl #32 - b.hs L(ge_64) + b.lo L(le_63) - /* Small data -- original count is less than 64 bytes. */ + stp q16, q16, [dstin, #0x20] + tbz count, #7, L(le_127) + + stp q16, q16, [dstin, #0x40] + stp q16, q16, [dstin, #0x60] + stp q16, q16, [dstend, #-0x80] + stp q16, q16, [dstend, #-0x60] +L(le_127): + stp q16, q16, [dstend, #-0x40] L(le_63): - cmp count, #16 - b.lo L(le_15) - stp val, val, [dstin] - tbz count, #5, L(le_31) - stp val, val, [dstin, #16] - stp val, val, [dstend, #-32] -L(le_31): - stp val, val, [dstend, #-16] - RET - .p2align 6,,16 -L(le_15): - tbz count, #3, L(le_7) - str val, [dstin] - str val, [dstend, #-8] - RET - .p2align 6,,16 -L(le_7): - tbz count, #2, L(le_3) - str valw, [dstin] - str valw, [dstend, #-4] - RET - .p2align 6,,20 -L(le_3): - tbz count, #1, L(le_1) - strh valw, [dstend, #-2] -L(le_1): - tbz count, #0, L(le_0) - strb valw, [dstin] -L(le_0): + stp q16, q16, [dstend, #-0x20] RET - .p2align 6 -L(ge_64): - and dst, dstin, #-16 /* align the pointer / pre-bias. */ - stp val, val, [dstin] /* first 16 align 1 */ + .p2align 6,,16 +L(ge_256): + and dst, dstin, #-32 /* align the pointer / pre-bias. */ + stp q16, q16, [dstin] /* first 32 align 1 */ sub count, dstend, dst /* begin misalign recompute */ - subs count, count, #16+64 /* finish recompute + pre-bias */ - b.ls L(loop_tail) + sub count, count, #32+128 /* finish recompute + pre-bias */ .p2align 6,,24 L(loop): - stp val, val, [dst, #16] - stp val, val, [dst, #32] - subs count, count, #64 - stp val, val, [dst, #48] - stp val, val, [dst, #64]! + stp q16, q16, [dst, #0x20] + stp q16, q16, [dst, #0x40] + subs count, count, #128 + stp q16, q16, [dst, #0x60] + stp q16, q16, [dst, #0x80]! b.hs L(loop) - adds count, count, #64 /* undo pre-bias */ + adds count, count, #128 /* undo pre-bias */ b.ne L(loop_tail) RET /* Tail of the zva loop. Less than ZVA bytes, but possibly lots - more than 64. Note that dst is aligned but unbiased. */ + more than 128. Note that dst is aligned but unbiased. */ L(zva_tail): - subs count, count, #64 /* pre-bias */ - sub dst, dst, #16 /* pre-bias */ + subs count, count, #128 /* pre-bias */ + sub dst, dst, #32 /* pre-bias */ b.hi L(loop) - /* Tail of the stp loop; less than 64 bytes left. - Note that dst is still aligned and biased by -16. */ + /* Tail of the stp loop; less than 128 bytes left. + Note that dst is still aligned and biased by -32. */ L(loop_tail): - stp val, val, [dstend, #-64] - stp val, val, [dstend, #-48] - stp val, val, [dstend, #-32] - stp val, val, [dstend, #-16] + stp q16, q16, [dstend, #-0x80] + stp q16, q16, [dstend, #-0x60] + stp q16, q16, [dstend, #-0x40] + stp q16, q16, [dstend, #-0x20] + RET + +L(le_31): + tbz count, #4, L(le_15) + str q16, [dstin] + str q16, [dstend, #-0x10] + RET +L(le_15): + tbz count, #3, L(le_7) + str d16, [dstin] + str d16, [dstend, #-8] + RET +L(le_7): + tbz count, #2, L(le_3) + str s16, [dstin] + str s16, [dstend, #-4] + RET +L(le_3): + tbz count, #1, L(le_1) + str h16, [dstend, #-2] +L(le_1): + tbz count, #0, L(le_0) + str b16, [dstin] +L(le_0): RET .size memset_nozva, . - memset_nozva |