123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- ;------------------------------------------------------------------------------
- ;
- ; CopyMem() worker for ARM
- ;
- ; This file started out as C code that did 64 bit moves if the buffer was
- ; 32-bit aligned, else it does a byte copy. It also does a byte copy for
- ; any trailing bytes. It was updated to do 32-byte copies using stm/ldm.
- ;
- ; Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
- ; This program and the accompanying materials
- ; are licensed and made available under the terms and conditions of the BSD License
- ; which accompanies this distribution. The full text of the license may be found at
- ; http://opensource.org/licenses/bsd-license.php
- ;
- ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
- ;
- ;------------------------------------------------------------------------------
- /**
- Copy Length bytes from Source to Destination. Overlap is OK.
- This implementation
- @param Destination Target of copy
- @param Source Place to copy from
- @param Length Number of bytes to copy
- @return Destination
- VOID *
- EFIAPI
- InternalMemCopyMem (
- OUT VOID *DestinationBuffer,
- IN CONST VOID *SourceBuffer,
- IN UINTN Length
- )
- **/
- EXPORT InternalMemCopyMem
- AREA AsmMemStuff, CODE, READONLY
- InternalMemCopyMem
- stmfd sp!, {r4-r11, lr}
- // Save the input parameters in extra registers (r11 = destination, r14 = source, r12 = length)
- mov r11, r0
- mov r10, r0
- mov r12, r2
- mov r14, r1
- memcopy_check_overlapped
- cmp r11, r1
- // If (dest < source)
- bcc memcopy_check_optim_default
- // If (dest <= source). But with the previous condition -> If (dest == source)
- bls memcopy_end
- // If (source + length < dest)
- rsb r3, r1, r11
- cmp r12, r3
- bcc memcopy_check_optim_default
- // If (length == 0)
- cmp r12, #0
- beq memcopy_end
- b memcopy_check_optim_overlap
- memcopy_check_optim_default
- // Check if we can use an optimized path ((length >= 32) && destination word-aligned && source word-aligned) for the memcopy (optimized path if r0 == 1)
- tst r0, #0xF
- movne r0, #0
- bne memcopy_default
- tst r1, #0xF
- movne r3, #0
- moveq r3, #1
- cmp r2, #31
- movls r0, #0
- andhi r0, r3, #1
- b memcopy_default
- memcopy_check_optim_overlap
- // r10 = dest_end, r14 = source_end
- add r10, r11, r12
- add r14, r12, r1
- // Are we in the optimized case ((length >= 32) && dest_end word-aligned && source_end word-aligned)
- cmp r2, #31
- movls r0, #0
- movhi r0, #1
- tst r10, #0xF
- movne r0, #0
- tst r14, #0xF
- movne r0, #0
- b memcopy_overlapped
- memcopy_overlapped_non_optim
- // We read 1 byte from the end of the source buffer
- sub r3, r14, #1
- sub r12, r12, #1
- ldrb r3, [r3, #0]
- sub r2, r10, #1
- cmp r12, #0
- // We write 1 byte at the end of the dest buffer
- sub r10, r10, #1
- sub r14, r14, #1
- strb r3, [r2, #0]
- bne memcopy_overlapped_non_optim
- b memcopy_end
- // r10 = dest_end, r14 = source_end
- memcopy_overlapped
- // Are we in the optimized case ?
- cmp r0, #0
- beq memcopy_overlapped_non_optim
- // Optimized Overlapped - Read 32 bytes
- sub r14, r14, #32
- sub r12, r12, #32
- cmp r12, #31
- ldmia r14, {r2-r9}
- // If length is less than 32 then disable optim
- movls r0, #0
- cmp r12, #0
- // Optimized Overlapped - Write 32 bytes
- sub r10, r10, #32
- stmia r10, {r2-r9}
- // while (length != 0)
- bne memcopy_overlapped
- b memcopy_end
- memcopy_default_non_optim
- // Byte copy
- ldrb r3, [r14], #1
- sub r12, r12, #1
- strb r3, [r10], #1
- memcopy_default
- cmp r12, #0
- beq memcopy_end
- // r10 = dest, r14 = source
- memcopy_default_loop
- cmp r0, #0
- beq memcopy_default_non_optim
- // Optimized memcopy - Read 32 Bytes
- sub r12, r12, #32
- cmp r12, #31
- ldmia r14!, {r2-r9}
- // If length is less than 32 then disable optim
- movls r0, #0
- cmp r12, #0
- // Optimized memcopy - Write 32 Bytes
- stmia r10!, {r2-r9}
- // while (length != 0)
- bne memcopy_default_loop
- memcopy_end
- mov r0, r11
- ldmfd sp!, {r4-r11, pc}
- END
|