mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
PowerPC: memset optimization for POWER8/PPC64
This patch adds an optimized memset implementation for POWER8. For sizes from 0 to 255 bytes, a word/doubleword algorithm similar to POWER7 optimized one is used. For size higher than 255 two strategies are used: 1. If the constant is different than 0, the memory is written with altivec vector instruction; 2. If constant is 0, dbcz instructions are used. The loop is unrolled to clear 512 byte at time. Using vector instructions increases throughput considerable, with a double performance for sizes larger than 1024. The dcbz loops unrolls also shows performance improvement, by doubling throughput for sizes larger than 8192 bytes.
This commit is contained in:
parent
3b473fecdf
commit
71ae86478e
15
ChangeLog
15
ChangeLog
@ -1,5 +1,20 @@
|
||||
2014-09-10 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
|
||||
|
||||
* benchtests/bench-memset.c (test_main): Add more test from size
|
||||
from 32 to 512 bytes.
|
||||
* sysdeps/powerpc/powerpc64/multiarch/Makefile [sysdep_routines]:
|
||||
Add POWER8 memset object.
|
||||
* sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Add POWER8 memset and bzero implementations.
|
||||
* sysdeps/powerpc/powerpc64/multiarch/bzero.c (__bzero): Add POWER8
|
||||
implementation.
|
||||
* sysdeps/powerpc/powerpc64/multiarch/memset.c (__libc_memset):
|
||||
Likewise.
|
||||
* sysdeps/powerpc/powerpc64/multiarch/memset-power8.S: New file:
|
||||
multiarch POWER8 memset optimization.
|
||||
* sysdeps/powerpc/powerpc64/power8/memset.S: New file: optimized
|
||||
POWER8 memset optimization.
|
||||
|
||||
* sysdeps/powerpc/powerpc64/multiarch/Makefile [sysdep_routines]:
|
||||
Remove bzero multiarch objects.
|
||||
* sysdeps/powerpc/powerpc64/multiarch/bzero-power4.S: Remove file.
|
||||
|
@ -150,6 +150,11 @@ test_main (void)
|
||||
if (i & (i - 1))
|
||||
do_test (0, c, i);
|
||||
}
|
||||
for (i = 32; i < 512; i+=32)
|
||||
{
|
||||
do_test (0, c, i);
|
||||
do_test (i, c, i);
|
||||
}
|
||||
do_test (1, c, 14);
|
||||
do_test (3, c, 1024);
|
||||
do_test (4, c, 64);
|
||||
|
@ -2,7 +2,7 @@ ifeq ($(subdir),string)
|
||||
sysdep_routines += memcpy-power7 memcpy-a2 memcpy-power6 memcpy-cell \
|
||||
memcpy-power4 memcpy-ppc64 memcmp-power7 memcmp-power4 \
|
||||
memcmp-ppc64 memset-power7 memset-power6 memset-power4 \
|
||||
memset-ppc64 \
|
||||
memset-ppc64 memset-power8 \
|
||||
mempcpy-power7 mempcpy-ppc64 memchr-power7 memchr-ppc64 \
|
||||
memrchr-power7 memrchr-ppc64 rawmemchr-power7 \
|
||||
rawmemchr-ppc64 strlen-power7 strlen-ppc64 strnlen-power7 \
|
||||
|
@ -26,14 +26,17 @@ extern __typeof (bzero) __bzero_ppc attribute_hidden;
|
||||
extern __typeof (bzero) __bzero_power4 attribute_hidden;
|
||||
extern __typeof (bzero) __bzero_power6 attribute_hidden;
|
||||
extern __typeof (bzero) __bzero_power7 attribute_hidden;
|
||||
extern __typeof (bzero) __bzero_power8 attribute_hidden;
|
||||
|
||||
libc_ifunc (__bzero,
|
||||
(hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __bzero_power7 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __bzero_power8 :
|
||||
(hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __bzero_power7 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
? __bzero_power6 :
|
||||
(hwcap & PPC_FEATURE_POWER4)
|
||||
? __bzero_power4
|
||||
? __bzero_power4
|
||||
: __bzero_ppc);
|
||||
|
||||
weak_alias (__bzero, bzero)
|
||||
|
@ -34,6 +34,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
size_t i = 0;
|
||||
|
||||
unsigned long int hwcap = GLRO(dl_hwcap);
|
||||
unsigned long int hwcap2 = GLRO(dl_hwcap2);
|
||||
|
||||
/* hwcap contains only the latest supported ISA, the code checks which is
|
||||
and fills the previous supported ones. */
|
||||
if (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
@ -69,6 +71,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/memset.c. */
|
||||
IFUNC_IMPL (i, name, memset,
|
||||
IFUNC_IMPL_ADD (array, i, memset, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__memset_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__memset_power7)
|
||||
IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_05,
|
||||
@ -134,6 +138,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/bzero.c. */
|
||||
IFUNC_IMPL (i, name, bzero,
|
||||
IFUNC_IMPL_ADD (array, i, bzero, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__bzero_power8)
|
||||
IFUNC_IMPL_ADD (array, i, bzero, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__bzero_power7)
|
||||
IFUNC_IMPL_ADD (array, i, bzero, hwcap & PPC_FEATURE_ARCH_2_05,
|
||||
|
43
sysdeps/powerpc/powerpc64/multiarch/memset-power8.S
Normal file
43
sysdeps/powerpc/powerpc64/multiarch/memset-power8.S
Normal file
@ -0,0 +1,43 @@
|
||||
/* Optimized memset implementation for PowerPC64/POWER8.
|
||||
Copyright (C) 2014 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
#undef EALIGN
|
||||
#define EALIGN(name, alignt, words) \
|
||||
.section ".text"; \
|
||||
ENTRY_2(__memset_power8) \
|
||||
.align ALIGNARG(alignt); \
|
||||
EALIGN_W_##words; \
|
||||
BODY_LABEL(__memset_power8): \
|
||||
cfi_startproc; \
|
||||
LOCALENTRY(__memset_power8)
|
||||
|
||||
#undef END_GEN_TB
|
||||
#define END_GEN_TB(name, mask) \
|
||||
cfi_endproc; \
|
||||
TRACEBACK_MASK(__memset_power8,mask) \
|
||||
END_2(__memset_power8)
|
||||
|
||||
#undef libc_hidden_builtin_def
|
||||
#define libc_hidden_builtin_def(name)
|
||||
|
||||
#undef __bzero
|
||||
#define __bzero __bzero_power8
|
||||
|
||||
#include <sysdeps/powerpc/powerpc64/power8/memset.S>
|
@ -32,16 +32,19 @@ extern __typeof (__redirect_memset) __memset_ppc attribute_hidden;
|
||||
extern __typeof (__redirect_memset) __memset_power4 attribute_hidden;
|
||||
extern __typeof (__redirect_memset) __memset_power6 attribute_hidden;
|
||||
extern __typeof (__redirect_memset) __memset_power7 attribute_hidden;
|
||||
extern __typeof (__redirect_memset) __memset_power8 attribute_hidden;
|
||||
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc (__libc_memset,
|
||||
(hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __memset_power7 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __memset_power8 :
|
||||
(hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __memset_power7 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
? __memset_power6 :
|
||||
(hwcap & PPC_FEATURE_POWER4)
|
||||
? __memset_power4
|
||||
? __memset_power4
|
||||
: __memset_ppc);
|
||||
|
||||
#undef memset
|
||||
|
449
sysdeps/powerpc/powerpc64/power8/memset.S
Normal file
449
sysdeps/powerpc/powerpc64/power8/memset.S
Normal file
@ -0,0 +1,449 @@
|
||||
/* Optimized memset implementation for PowerPC64/POWER8.
|
||||
Copyright (C) 2014 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
/* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
|
||||
Returns 's'. */
|
||||
|
||||
.machine power8
|
||||
EALIGN (memset, 5, 0)
|
||||
CALL_MCOUNT 3
|
||||
|
||||
L(_memset):
|
||||
cmpldi cr7,r5,31
|
||||
neg r0,r3
|
||||
mr r10,r3
|
||||
|
||||
insrdi r4,r4,8,48
|
||||
insrdi r4,r4,16,32 /* Replicate byte to word. */
|
||||
ble cr7,L(write_LT_32)
|
||||
|
||||
andi. r11,r10,15 /* Check alignment of DST. */
|
||||
insrdi r4,r4,32,0 /* Replicate word to double word. */
|
||||
|
||||
beq L(big_aligned)
|
||||
|
||||
mtocrf 0x01,r0
|
||||
clrldi r0,r0,60
|
||||
|
||||
/* Get DST aligned to 16 bytes. */
|
||||
1: bf 31,2f
|
||||
stb r4,0(r10)
|
||||
addi r10,r10,1
|
||||
|
||||
2: bf 30,4f
|
||||
sth r4,0(r10)
|
||||
addi r10,r10,2
|
||||
|
||||
4: bf 29,8f
|
||||
stw r4,0(r10)
|
||||
addi r10,r10,4
|
||||
|
||||
8: bf 28,16f
|
||||
std r4,0(r10)
|
||||
addi r10,r10,8
|
||||
|
||||
16: subf r5,r0,r5
|
||||
|
||||
.align 4
|
||||
L(big_aligned):
|
||||
/* For sizes larger than 255 two possible paths:
|
||||
- if constant is '0', zero full cache lines with dcbz
|
||||
- otherwise uses vector instructions. */
|
||||
cmpldi cr5,r5,255
|
||||
dcbtst 0,r10
|
||||
cmpldi cr6,r4,0
|
||||
crand 27,26,21
|
||||
bt 27,L(huge_dcbz)
|
||||
bge cr5,L(huge_vector)
|
||||
|
||||
|
||||
/* Size between 32 and 255 bytes with constant different than 0, use
|
||||
doubleword store instruction to achieve best throughput. */
|
||||
srdi r8,r5,5
|
||||
clrldi r11,r5,59
|
||||
cmpldi cr6,r11,0
|
||||
cmpdi r8,0
|
||||
beq L(tail_bytes)
|
||||
mtctr r8
|
||||
|
||||
/* Main aligned write loop, writes 32-bytes at a time. */
|
||||
.align 4
|
||||
L(big_loop):
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
std r4,16(r10)
|
||||
std r4,24(r10)
|
||||
addi r10,r10,32
|
||||
bdz L(tail_bytes)
|
||||
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
std r4,16(r10)
|
||||
std r4,24(r10)
|
||||
addi r10,10,32
|
||||
bdnz L(big_loop)
|
||||
|
||||
b L(tail_bytes)
|
||||
|
||||
/* Write remaining 1~31 bytes. */
|
||||
.align 4
|
||||
L(tail_bytes):
|
||||
beqlr cr6
|
||||
|
||||
srdi r7,r11,4
|
||||
clrldi r8,r11,60
|
||||
mtocrf 0x01,r7
|
||||
|
||||
.align 4
|
||||
bf 31,8f
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
addi r10,r10,16
|
||||
|
||||
.align 4
|
||||
8: mtocrf 0x1,r8
|
||||
bf 28,4f
|
||||
std r4,0(r10)
|
||||
addi r10,r10,8
|
||||
|
||||
.align 4
|
||||
4: bf 29,2f
|
||||
stw 4,0(10)
|
||||
addi 10,10,4
|
||||
|
||||
.align 4
|
||||
2: bf 30,1f
|
||||
sth 4,0(10)
|
||||
addi 10,10,2
|
||||
|
||||
.align 4
|
||||
1: bflr 31
|
||||
stb 4,0(10)
|
||||
blr
|
||||
|
||||
/* Size larger than 255 bytes with constant different than 0, use
|
||||
vector instruction to achieve best throughput. */
|
||||
L(huge_vector):
|
||||
/* Replicate set byte to quadword in VMX register. */
|
||||
mtvsrd v1,r4
|
||||
xxpermdi 32,v0,v1,0
|
||||
vspltb v2,v0,15
|
||||
|
||||
/* Main aligned write loop: 128 bytes at a time. */
|
||||
li r6,16
|
||||
li r7,32
|
||||
li r8,48
|
||||
mtocrf 0x02,r5
|
||||
srdi r12,r5,7
|
||||
cmpdi r12,0
|
||||
beq L(aligned_tail)
|
||||
mtctr r12
|
||||
b L(aligned_128loop)
|
||||
|
||||
.align 4
|
||||
L(aligned_128loop):
|
||||
stvx v2,0,r10
|
||||
stvx v2,r10,r6
|
||||
stvx v2,r10,r7
|
||||
stvx v2,r10,r8
|
||||
addi r10,r10,64
|
||||
stvx v2,0,r10
|
||||
stvx v2,r10,r6
|
||||
stvx v2,r10,r7
|
||||
stvx v2,r10,r8
|
||||
addi r10,r10,64
|
||||
bdnz L(aligned_128loop)
|
||||
|
||||
/* Write remaining 1~127 bytes. */
|
||||
L(aligned_tail):
|
||||
mtocrf 0x01,r5
|
||||
bf 25,32f
|
||||
stvx v2,0,r10
|
||||
stvx v2,r10,r6
|
||||
stvx v2,r10,r7
|
||||
stvx v2,r10,r8
|
||||
addi r10,r10,64
|
||||
|
||||
32: bf 26,16f
|
||||
stvx v2,0,r10
|
||||
stvx v2,r10,r6
|
||||
addi r10,r10,32
|
||||
|
||||
16: bf 27,8f
|
||||
stvx v2,0,r10
|
||||
addi r10,r10,16
|
||||
|
||||
8: bf 28,4f
|
||||
std r4,0(r10)
|
||||
addi r10,r10,8
|
||||
|
||||
/* Copies 4~7 bytes. */
|
||||
4: bf 29,L(tail2)
|
||||
stw r4,0(r10)
|
||||
bf 30,L(tail5)
|
||||
sth r4,4(r10)
|
||||
bflr 31
|
||||
stb r4,6(r10)
|
||||
/* Return original DST pointer. */
|
||||
blr
|
||||
|
||||
/* Special case when value is 0 and we have a long length to deal
|
||||
with. Use dcbz to zero out a full cacheline of 128 bytes at a time.
|
||||
Before using dcbz though, we need to get the destination 128-byte
|
||||
aligned. */
|
||||
.align 4
|
||||
L(huge_dcbz):
|
||||
andi. r11,r10,127
|
||||
neg r0,r10
|
||||
beq L(huge_dcbz_aligned)
|
||||
|
||||
clrldi r0,r0,57
|
||||
subf r5,r0,r5
|
||||
srdi r0,r0,3
|
||||
mtocrf 0x01,r0
|
||||
|
||||
/* Write 1~128 bytes until DST is aligned to 128 bytes. */
|
||||
8: bf 28,4f
|
||||
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
std r4,16(r10)
|
||||
std r4,24(r10)
|
||||
std r4,32(r10)
|
||||
std r4,40(r10)
|
||||
std r4,48(r10)
|
||||
std r4,56(r10)
|
||||
addi r10,r10,64
|
||||
|
||||
.align 4
|
||||
4: bf 29,2f
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
std r4,16(r10)
|
||||
std r4,24(r10)
|
||||
addi r10,r10,32
|
||||
|
||||
.align 4
|
||||
2: bf 30,1f
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
addi r10,r10,16
|
||||
|
||||
.align 4
|
||||
1: bf 31,L(huge_dcbz_aligned)
|
||||
std r4,0(r10)
|
||||
addi r10,r10,8
|
||||
|
||||
L(huge_dcbz_aligned):
|
||||
/* Setup dcbz unroll offsets and count numbers. */
|
||||
srdi r8,r5,9
|
||||
clrldi r11,r5,55
|
||||
cmpldi cr6,r11,0
|
||||
li r9,128
|
||||
cmpdi r8,0
|
||||
beq L(huge_tail)
|
||||
li r7,256
|
||||
li r6,384
|
||||
mtctr r8
|
||||
|
||||
.align 4
|
||||
L(huge_loop):
|
||||
/* Sets 512 bytes to zero in each iteration, the loop unrolling shows
|
||||
a throughput boost for large sizes (2048 bytes or higher). */
|
||||
dcbz 0,r10
|
||||
dcbz r9,r10
|
||||
dcbz r7,r10
|
||||
dcbz r6,r10
|
||||
addi r10,r10,512
|
||||
bdnz L(huge_loop)
|
||||
|
||||
beqlr cr6
|
||||
|
||||
L(huge_tail):
|
||||
srdi r6,r11,8
|
||||
srdi r7,r11,4
|
||||
clrldi r8,r11,4
|
||||
cmpldi cr6,r8,0
|
||||
mtocrf 0x01,r6
|
||||
|
||||
beq cr6,L(tail)
|
||||
|
||||
/* We have 1~511 bytes remaining. */
|
||||
.align 4
|
||||
32: bf 31,16f
|
||||
dcbz 0,r10
|
||||
dcbz r9,r10
|
||||
addi r10,r10,256
|
||||
|
||||
.align 4
|
||||
16: mtocrf 0x01,r7
|
||||
bf 28,8f
|
||||
dcbz 0,r10
|
||||
addi r10,r10,128
|
||||
|
||||
.align 4
|
||||
8: bf 29,4f
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
std r4,16(r10)
|
||||
std r4,24(r10)
|
||||
std r4,32(r10)
|
||||
std r4,40(r10)
|
||||
std r4,48(r10)
|
||||
std r4,56(r10)
|
||||
addi r10,r10,64
|
||||
|
||||
.align 4
|
||||
4: bf 30,2f
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
std r4,16(r10)
|
||||
std r4,24(r10)
|
||||
addi r10,r10,32
|
||||
|
||||
.align 4
|
||||
2: bf 31,L(tail)
|
||||
std r4,0(r10)
|
||||
std r4,8(r10)
|
||||
addi r10,r10,16
|
||||
.align 4
|
||||
|
||||
/* Remaining 1~15 bytes. */
|
||||
L(tail):
|
||||
mtocrf 0x01,r8
|
||||
|
||||
.align
|
||||
8: bf 28,4f
|
||||
std r4,0(r10)
|
||||
addi r10,r10,8
|
||||
|
||||
.align 4
|
||||
4: bf 29,2f
|
||||
stw r4,0(r10)
|
||||
addi r10,r10,4
|
||||
|
||||
.align 4
|
||||
2: bf 30,1f
|
||||
sth r4,0(r10)
|
||||
addi r10,r10,2
|
||||
|
||||
.align 4
|
||||
1: bflr 31
|
||||
stb r4,0(r10)
|
||||
blr
|
||||
|
||||
/* Handle short copies of 0~31 bytes. Best throughput is achieved
|
||||
by just unrolling all operations. */
|
||||
.align 4
|
||||
L(write_LT_32):
|
||||
cmpldi cr6,5,8
|
||||
mtocrf 0x01,r5
|
||||
ble cr6,L(write_LE_8)
|
||||
|
||||
/* At least 9 bytes to go. */
|
||||
neg r8,r4
|
||||
andi. r0,r8,3
|
||||
cmpldi cr1,r5,16
|
||||
beq L(write_LT_32_aligned)
|
||||
|
||||
/* Force 4-byte alignment for SRC. */
|
||||
mtocrf 0x01,r0
|
||||
subf r5,r0,r5
|
||||
|
||||
2: bf 30,1f
|
||||
sth r4,0(r10)
|
||||
addi r10,r10,2
|
||||
|
||||
1: bf 31,L(end_4bytes_alignment)
|
||||
stb r4,0(r10)
|
||||
addi r10,r10,1
|
||||
|
||||
.align 4
|
||||
L(end_4bytes_alignment):
|
||||
cmpldi cr1,r5,16
|
||||
mtocrf 0x01,r5
|
||||
|
||||
L(write_LT_32_aligned):
|
||||
blt cr1,8f
|
||||
|
||||
stw r4,0(r10)
|
||||
stw r4,4(r10)
|
||||
stw r4,8(r10)
|
||||
stw r4,12(r10)
|
||||
addi r10,r10,16
|
||||
|
||||
8: bf 28,L(tail4)
|
||||
stw r4,0(r10)
|
||||
stw r4,4(r10)
|
||||
addi r10,r10,8
|
||||
|
||||
.align 4
|
||||
/* Copies 4~7 bytes. */
|
||||
L(tail4):
|
||||
bf 29,L(tail2)
|
||||
stw r4,0(r10)
|
||||
bf 30,L(tail5)
|
||||
sth r4,4(r10)
|
||||
bflr 31
|
||||
stb r4,6(r10)
|
||||
blr
|
||||
|
||||
.align 4
|
||||
/* Copies 2~3 bytes. */
|
||||
L(tail2):
|
||||
bf 30,1f
|
||||
sth r4,0(r10)
|
||||
bflr 31
|
||||
stb r4,2(r10)
|
||||
blr
|
||||
|
||||
.align 4
|
||||
L(tail5):
|
||||
bflr 31
|
||||
stb r4,4(r10)
|
||||
blr
|
||||
|
||||
.align 4
|
||||
1: bflr 31
|
||||
stb r4,0(r10)
|
||||
blr
|
||||
|
||||
/* Handles copies of 0~8 bytes. */
|
||||
.align 4
|
||||
L(write_LE_8):
|
||||
bne cr6,L(tail4)
|
||||
|
||||
stw r4,0(r10)
|
||||
stw r4,4(r10)
|
||||
blr
|
||||
END_GEN_TB (memset,TB_TOCLESS)
|
||||
libc_hidden_builtin_def (memset)
|
||||
|
||||
/* Copied from bzero.S to prevent the linker from inserting a stub
|
||||
between bzero and memset. */
|
||||
ENTRY (__bzero)
|
||||
CALL_MCOUNT 3
|
||||
mr r5,r4
|
||||
li r4,0
|
||||
b L(_memset)
|
||||
END (__bzero)
|
||||
#ifndef __bzero
|
||||
weak_alias (__bzero, bzero)
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user