]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S
MdePkg/BaseMemoryLibOptDxe ARM: add missing function annotations
[mirror_edk2.git] / MdePkg / Library / BaseMemoryLibOptDxe / Arm / CopyMem.S
1 #------------------------------------------------------------------------------
2 #
3 # CopyMem() worker for ARM
4 #
5 # This file started out as C code that did 64 bit moves if the buffer was
6 # 32-bit aligned, else it does a byte copy. It also does a byte copy for
7 # any trailing bytes. It was updated to do 32-byte copies using stm/ldm.
8 #
9 # Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
10 # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
11 # This program and the accompanying materials
12 # are licensed and made available under the terms and conditions of the BSD License
13 # which accompanies this distribution. The full text of the license may be found at
14 # http://opensource.org/licenses/bsd-license.php
15 #
16 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #
19 #------------------------------------------------------------------------------
20
21 .text
22 .thumb
23 .syntax unified
24
25 /**
26 Copy Length bytes from Source to Destination. Overlap is OK.
27
28 This implementation
29
30 @param Destination Target of copy
31 @param Source Place to copy from
32 @param Length Number of bytes to copy
33
34 @return Destination
35
36
37 VOID *
38 EFIAPI
39 InternalMemCopyMem (
40 OUT VOID *DestinationBuffer,
41 IN CONST VOID *SourceBuffer,
42 IN UINTN Length
43 )
44 **/
45 .type ASM_PFX(InternalMemCopyMem), %function
46 ASM_GLOBAL ASM_PFX(InternalMemCopyMem)
47 ASM_PFX(InternalMemCopyMem):
48 push {r4-r11, lr}
49 // Save the input parameters in extra registers (r11 = destination, r14 = source, r12 = length)
50 mov r11, r0
51 mov r10, r0
52 mov r12, r2
53 mov r14, r1
54
55 cmp r11, r1
56 // If (dest < source)
57 bcc memcopy_check_optim_default
58
59 // If (source + length < dest)
60 rsb r3, r1, r11
61 cmp r12, r3
62 bcc memcopy_check_optim_default
63 b memcopy_check_optim_overlap
64
65 memcopy_check_optim_default:
66 // Check if we can use an optimized path ((length >= 32) && destination word-aligned && source word-aligned) for the memcopy (optimized path if r0 == 1)
67 tst r0, #0xF
68 it ne
69 movne.n r0, #0
70 bne memcopy_default
71 tst r1, #0xF
72 it ne
73 movne.n r3, #0
74 it eq
75 moveq.n r3, #1
76 cmp r2, #31
77 it ls
78 movls.n r0, #0
79 bls memcopy_default
80 and r0, r3, #1
81 b memcopy_default
82
83 memcopy_check_optim_overlap:
84 // r10 = dest_end, r14 = source_end
85 add r10, r11, r12
86 add r14, r12, r1
87
88 // Are we in the optimized case ((length >= 32) && dest_end word-aligned && source_end word-aligned)
89 cmp r2, #31
90 it ls
91 movls.n r0, #0
92 it hi
93 movhi.n r0, #1
94 tst r10, #0xF
95 it ne
96 movne.n r0, #0
97 tst r14, #0xF
98 it ne
99 movne.n r0, #0
100 b memcopy_overlapped
101
102 memcopy_overlapped_non_optim:
103 // We read 1 byte from the end of the source buffer
104 sub r3, r14, #1
105 sub r12, r12, #1
106 ldrb r3, [r3, #0]
107 sub r2, r10, #1
108 cmp r12, #0
109 // We write 1 byte at the end of the dest buffer
110 sub r10, r10, #1
111 sub r14, r14, #1
112 strb r3, [r2, #0]
113 bne memcopy_overlapped_non_optim
114 b memcopy_end
115
116 // r10 = dest_end, r14 = source_end
117 memcopy_overlapped:
118 // Are we in the optimized case ?
119 cmp r0, #0
120 beq memcopy_overlapped_non_optim
121
122 // Optimized Overlapped - Read 32 bytes
123 sub r14, r14, #32
124 sub r12, r12, #32
125 cmp r12, #31
126 ldmia r14, {r2-r9}
127
128 // If length is less than 32 then disable optim
129 it ls
130 movls.n r0, #0
131
132 cmp r12, #0
133
134 // Optimized Overlapped - Write 32 bytes
135 sub r10, r10, #32
136 stmia r10, {r2-r9}
137
138 // while (length != 0)
139 bne memcopy_overlapped
140 b memcopy_end
141
142 memcopy_default_non_optim:
143 // Byte copy
144 ldrb r3, [r14], #1
145 sub r12, r12, #1
146 strb r3, [r10], #1
147
148 memcopy_default:
149 cmp r12, #0
150 beq memcopy_end
151
152 // r10 = dest, r14 = source
153 memcopy_default_loop:
154 cmp r0, #0
155 beq memcopy_default_non_optim
156
157 // Optimized memcopy - Read 32 Bytes
158 sub r12, r12, #32
159 cmp r12, #31
160 ldmia r14!, {r2-r9}
161
162 // If length is less than 32 then disable optim
163 it ls
164 movls.n r0, #0
165
166 cmp r12, #0
167
168 // Optimized memcopy - Write 32 Bytes
169 stmia r10!, {r2-r9}
170
171 // while (length != 0)
172 bne memcopy_default_loop
173
174 memcopy_end:
175 mov r0, r11
176 pop {r4-r11, pc}