This adds the Arm Optimized Routines (see https://github.com/ARM-software/optimized-routines) source code under the the LLVM license. The version of the code provided in this patch is v20.02 of the Arm Optimized Routines project. This entire contribution is being committed as is even though it does not currently fit the LLVM libc model and does not follow the LLVM coding style. In the near future, implementations from this patch will be moved over to their right place in the LLVM-libc tree. This will be done over many small patches, all of which will go through the normal LLVM code review process. See this libc-dev post for the plan: http://lists.llvm.org/pipermail/libc-dev/2020-March/000044.html Differential revision of the original upload: https://reviews.llvm.org/D75355
116 lines
2.2 KiB
ArmAsm
116 lines
2.2 KiB
ArmAsm
/*
|
|
* memset - fill memory with a constant byte
|
|
*
|
|
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
* See https://llvm.org/LICENSE.txt for license information.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
/* Assumptions:
|
|
*
|
|
* ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
|
|
*
|
|
*/
|
|
|
|
#include "../asmdefs.h"
|
|
|
|
#define dstin x0
|
|
#define val x1
|
|
#define valw w1
|
|
#define count x2
|
|
#define dst x3
|
|
#define dstend x4
|
|
#define zva_val x5
|
|
|
|
ENTRY (__memset_aarch64)
|
|
|
|
dup v0.16B, valw
|
|
add dstend, dstin, count
|
|
|
|
cmp count, 96
|
|
b.hi L(set_long)
|
|
cmp count, 16
|
|
b.hs L(set_medium)
|
|
mov val, v0.D[0]
|
|
|
|
/* Set 0..15 bytes. */
|
|
tbz count, 3, 1f
|
|
str val, [dstin]
|
|
str val, [dstend, -8]
|
|
ret
|
|
nop
|
|
1: tbz count, 2, 2f
|
|
str valw, [dstin]
|
|
str valw, [dstend, -4]
|
|
ret
|
|
2: cbz count, 3f
|
|
strb valw, [dstin]
|
|
tbz count, 1, 3f
|
|
strh valw, [dstend, -2]
|
|
3: ret
|
|
|
|
/* Set 17..96 bytes. */
|
|
L(set_medium):
|
|
str q0, [dstin]
|
|
tbnz count, 6, L(set96)
|
|
str q0, [dstend, -16]
|
|
tbz count, 5, 1f
|
|
str q0, [dstin, 16]
|
|
str q0, [dstend, -32]
|
|
1: ret
|
|
|
|
.p2align 4
|
|
/* Set 64..96 bytes. Write 64 bytes from the start and
|
|
32 bytes from the end. */
|
|
L(set96):
|
|
str q0, [dstin, 16]
|
|
stp q0, q0, [dstin, 32]
|
|
stp q0, q0, [dstend, -32]
|
|
ret
|
|
|
|
.p2align 4
|
|
L(set_long):
|
|
and valw, valw, 255
|
|
bic dst, dstin, 15
|
|
str q0, [dstin]
|
|
cmp count, 160
|
|
ccmp valw, 0, 0, hs
|
|
b.ne L(no_zva)
|
|
|
|
#ifndef SKIP_ZVA_CHECK
|
|
mrs zva_val, dczid_el0
|
|
and zva_val, zva_val, 31
|
|
cmp zva_val, 4 /* ZVA size is 64 bytes. */
|
|
b.ne L(no_zva)
|
|
#endif
|
|
str q0, [dst, 16]
|
|
stp q0, q0, [dst, 32]
|
|
bic dst, dst, 63
|
|
sub count, dstend, dst /* Count is now 64 too large. */
|
|
sub count, count, 128 /* Adjust count and bias for loop. */
|
|
|
|
.p2align 4
|
|
L(zva_loop):
|
|
add dst, dst, 64
|
|
dc zva, dst
|
|
subs count, count, 64
|
|
b.hi L(zva_loop)
|
|
stp q0, q0, [dstend, -64]
|
|
stp q0, q0, [dstend, -32]
|
|
ret
|
|
|
|
L(no_zva):
|
|
sub count, dstend, dst /* Count is 16 too large. */
|
|
sub dst, dst, 16 /* Dst is biased by -32. */
|
|
sub count, count, 64 + 16 /* Adjust count and bias for loop. */
|
|
L(no_zva_loop):
|
|
stp q0, q0, [dst, 32]
|
|
stp q0, q0, [dst, 64]!
|
|
subs count, count, 64
|
|
b.hi L(no_zva_loop)
|
|
stp q0, q0, [dstend, -64]
|
|
stp q0, q0, [dstend, -32]
|
|
ret
|
|
|
|
END (__memset_aarch64)
|