/*
* Copyright ( C ) 2013 The Android Open Source Project
* All rights reserved .
* Copyright ( c ) 2013 - 2014 NVIDIA Corporation . All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in
* the documentation and / or other materials provided with the
* distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS
* OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY ,
* OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*/
#include <private/bionic_asm.h>
.text
.syntax unified
.fpu neon
#define CACHE_LINE_SIZE (64 )
#define MEMCPY_BLOCK_SIZE_SMALL (32768 )
#define MEMCPY_BLOCK_SIZE_MID (1048576 )
#define PREFETCH_DISTANCE_NEAR (CACHE_LINE_SIZE*4 )
#define PREFETCH_DISTANCE_MID (CACHE_LINE_SIZE*4 )
#define PREFETCH_DISTANCE_FAR (CACHE_LINE_SIZE*16 )
ENTRY(memmove_a15)
cmp r2, #0
cmpne r0, r1
bxeq lr
subs r3, r0, r1
bls .L_jump_to_memcpy
cmp r2, r3
bhi .L_reversed_memcpy
.L_jump_to_memcpy:
b __memcpy
.L_reversed_memcpy:
push {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
add r0, r0, r2
add r1, r1, r2
/* preload next cache line */
pld [r1, #-CACHE_LINE_SIZE]
pld [r1, #-CACHE_LINE_SIZE*2 ]
.L_reversed_memcpy_align_dest:
/* Deal with very small blocks (< 32bytes) asap */
cmp r2, #32
blo .L_reversed_memcpy_lt_32bytes
/* no need to align if len < 128 bytes */
cmp r2, #128
blo .L_reversed_memcpy_lt_128bytes
/* align destination to 64 bytes (1 cache line) */
ands r3, r0, #0 x3f
beq .L_reversed_memcpy_dispatch
sub r2, r2, r3
0 : /* copy 1 byte */
movs ip, r3, lsl #31
ldrbmi ip, [r1, #-1 ]!
strbmi ip, [r0, #-1 ]!
1 : /* copy 2 bytes */
ldrbcs ip, [r1, #-1 ]!
strbcs ip, [r0, #-1 ]!
ldrbcs ip, [r1, #-1 ]!
strbcs ip, [r0, #-1 ]!
2 : /* copy 4 bytes */
movs ip, r3, lsl #29
bpl 3 f
sub r1, r1, #4
sub r0, r0, #4
vld4.8 {d0[0 ], d1[0 ], d2[0 ], d3[0 ]}, [r1]
vst4.8 {d0[0 ], d1[0 ], d2[0 ], d3[0 ]}, [r0, :32 ]
3 : /* copy 8 bytes */
bcc 4 f
sub r1, r1, #8
sub r0, r0, #8
vld1.8 {d0}, [r1]
vst1.8 {d0}, [r0, :64 ]
4 : /* copy 16 bytes */
movs ip, r3, lsl #27
bpl 5 f
sub r1, r1, #16
sub r0, r0, #16
vld1.8 {q0}, [r1]
vst1.8 {q0}, [r0, :128 ]
5 : /* copy 32 bytes */
bcc .L_reversed_memcpy_dispatch
sub r1, r1, #32
sub r0, r0, #32
vld1.8 {q0, q1}, [r1]
vst1.8 {q0, q1}, [r0, :256 ]
.L_reversed_memcpy_dispatch:
/* preload more cache lines */
pld [r1, #-CACHE_LINE_SIZE*3 ]
pld [r1, #-CACHE_LINE_SIZE*4 ]
cmp r2, #MEMCPY_BLOCK_SIZE_SMALL
blo .L_reversed_memcpy_neon_pld_near
cmp r2, #MEMCPY_BLOCK_SIZE_MID
blo .L_reversed_memcpy_neon_pld_mid
b .L_reversed_memcpy_neon_pld_far
.L_reversed_memcpy_neon_pld_near:
/* less than 128 bytes? */
subs r2, r2, #128
blo 1 f
sub r1, r1, #32
sub r0, r0, #32
mov r3, #-32
.align 4
0 :
/* copy 128 bytes in each loop */
subs r2, r2, #128
/* preload to cache */
pld [r1, #-(PREFETCH_DISTANCE_NEAR+CACHE_LINE_SIZE*2 )+32 ]
/* copy a cache line */
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
/* preload to cache */
pld [r1, #-(PREFETCH_DISTANCE_NEAR+CACHE_LINE_SIZE*2 )+32 ]
/* copy a cache line */
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
bhs 0 b
add r1, r1, #32
add r0, r0, #32
1 :
adds r2, r2, #128
bne .L_reversed_memcpy_lt_128bytes
pop {r0, pc}
.L_reversed_memcpy_neon_pld_mid:
subs r2, r2, #128
sub r1, r1, #32
sub r0, r0, #32
mov r3, #-32
.align 4
0 :
/* copy 128 bytes in each loop */
subs r2, r2, #128
/* preload to cache */
pld [r1, #-(PREFETCH_DISTANCE_MID+CACHE_LINE_SIZE)+32 ]
/* copy a cache line */
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
/* preload to cache */
pld [r1, #-(PREFETCH_DISTANCE_MID+CACHE_LINE_SIZE)+32 ]
/* copy a cache line */
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
vld1.8 {q0, q1}, [r1], r3
vst1.8 {q0, q1}, [r0, :256 ], r3
bhs 0 b
add r1, r1, #32
add r0, r0, #32
1 :
adds r2, r2, #128
bne .L_reversed_memcpy_lt_128bytes
pop {r0, pc}
.L_reversed_memcpy_neon_pld_far:
sub r2, r2, #128
sub r0, r0, #128
sub r1, r1, #128
.align 4
0 :
/* copy 128 bytes in each loop */
subs r2, r2, #128
/* preload to cache */
pld [r1, #-(PREFETCH_DISTANCE_FAR+CACHE_LINE_SIZE*2 )+128 ]
pld [r1, #-(PREFETCH_DISTANCE_FAR+CACHE_LINE_SIZE)+128 ]
/* read */
vld1.8 {q0, q1}, [r1]!
vld1.8 {q2, q3}, [r1]!
vld1.8 {q8, q9}, [r1]!
vld1.8 {q10, q11}, [r1]!
/* write */
vst1.8 {q0, q1}, [r0, :256 ]!
vst1.8 {q2, q3}, [r0, :256 ]!
vst1.8 {q8, q9}, [r0, :256 ]!
vst1.8 {q10, q11}, [r0, :256 ]!
sub r0, r0, #256
sub r1, r1, #256
bhs 0 b
add r0, r0, #128
add r1, r1, #128
1 :
adds r2, r2, #128
bne .L_reversed_memcpy_lt_128bytes
pop {r0, pc}
.L_reversed_memcpy_lt_128bytes:
6 : /* copy 64 bytes */
movs ip, r2, lsl #26
bcc 5 f
sub r1, r1, #32
sub r0, r0, #32
vld1.8 {q0, q1}, [r1]
vst1.8 {q0, q1}, [r0]
sub r1, r1, #32
sub r0, r0, #32
vld1.8 {q0, q1}, [r1]
vst1.8 {q0, q1}, [r0]
5 : /* copy 32 bytes */
bpl 4 f
sub r1, r1, #32
sub r0, r0, #32
vld1.8 {q0, q1}, [r1]
vst1.8 {q0, q1}, [r0]
.L_reversed_memcpy_lt_32bytes:
4 : /* copy 16 bytes */
movs ip, r2, lsl #28
bcc 3 f
sub r1, r1, #16
sub r0, r0, #16
vld1.8 {q0}, [r1]
vst1.8 {q0}, [r0]
3 : /* copy 8 bytes */
bpl 2 f
sub r1, r1, #8
sub r0, r0, #8
vld1.8 {d0}, [r1]
vst1.8 {d0}, [r0]
2 : /* copy 4 bytes */
ands ip, r2, #0 x4
beq 1 f
sub r1, r1, #4
sub r0, r0, #4
vld4.8 {d0[0 ], d1[0 ], d2[0 ], d3[0 ]}, [r1]
vst4.8 {d0[0 ], d1[0 ], d2[0 ], d3[0 ]}, [r0]
1 : /* copy 2 bytes */
movs ip, r2, lsl #31
ldrbcs ip, [r1, #-1 ]!
strbcs ip, [r0, #-1 ]!
ldrbcs ip, [r1, #-1 ]!
strbcs ip, [r0, #-1 ]!
0 : /* copy 1 byte */
ldrbmi ip, [r1, #-1 ]!
strbmi ip, [r0, #-1 ]!
pop {r0, pc}
END(memmove_a15)
Messung V0.5 in Prozent C=94 H=82 G=88
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-28)
¤
*© Formatika GbR, Deutschland