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; This program and the accompanying materials
11; are licensed and made available under the terms and conditions of the BSD License
12; which accompanies this distribution.  The full text of the license may be found at
13; http://opensource.org/licenses/bsd-license.php
14;
15; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17;
18;------------------------------------------------------------------------------
19
20/**
21  Copy Length bytes from Source to Destination. Overlap is OK.
22
23  This implementation
24
25  @param  Destination Target of copy
26  @param  Source      Place to copy from
27  @param  Length      Number of bytes to copy
28
29  @return Destination
30
31
32VOID *
33EFIAPI
34InternalMemCopyMem (
35  OUT     VOID                      *DestinationBuffer,
36  IN      CONST VOID                *SourceBuffer,
37  IN      UINTN                     Length
38  )
39**/
40
41    INCLUDE AsmMacroExport.inc
42
43 RVCT_ASM_EXPORT InternalMemCopyMem
44  stmfd  sp!, {r4-r11, lr}
45  // Save the input parameters in extra registers (r11 = destination, r14 = source, r12 = length)
46  mov  r11, r0
47  mov  r10, r0
48  mov  r12, r2
49  mov  r14, r1
50
51memcopy_check_overlapped
52  cmp  r11, r1
53  // If (dest < source)
54  bcc  memcopy_check_optim_default
55  // If (dest <= source). But with the previous condition ->  If (dest == source)
56  bls  memcopy_end
57
58  // If (source + length < dest)
59  rsb  r3, r1, r11
60  cmp  r12, r3
61  bcc  memcopy_check_optim_default
62
63  // If (length == 0)
64  cmp  r12, #0
65  beq  memcopy_end
66
67  b     memcopy_check_optim_overlap
68
69memcopy_check_optim_default
70  // Check if we can use an optimized path ((length >= 32) && destination word-aligned && source word-aligned) for the memcopy (optimized path if r0 == 1)
71  tst  r0, #0xF
72  movne  r0, #0
73  bne   memcopy_default
74  tst  r1, #0xF
75  movne  r3, #0
76  moveq  r3, #1
77  cmp  r2, #31
78  movls  r0, #0
79  andhi  r0, r3, #1
80  b     memcopy_default
81
82memcopy_check_optim_overlap
83  // r10 = dest_end, r14 = source_end
84  add  r10, r11, r12
85  add  r14, r12, r1
86
87  // Are we in the optimized case ((length >= 32) && dest_end word-aligned && source_end word-aligned)
88  cmp  r2, #31
89  movls  r0, #0
90  movhi  r0, #1
91  tst  r10, #0xF
92  movne  r0, #0
93  tst  r14, #0xF
94  movne  r0, #0
95  b  memcopy_overlapped
96
97memcopy_overlapped_non_optim
98  // We read 1 byte from the end of the source buffer
99  sub  r3, r14, #1
100  sub  r12, r12, #1
101  ldrb  r3, [r3, #0]
102  sub  r2, r10, #1
103  cmp  r12, #0
104  // We write 1 byte at the end of the dest buffer
105  sub  r10, r10, #1
106  sub  r14, r14, #1
107  strb  r3, [r2, #0]
108  bne  memcopy_overlapped_non_optim
109  b   memcopy_end
110
111// r10 = dest_end, r14 = source_end
112memcopy_overlapped
113  // Are we in the optimized case ?
114  cmp  r0, #0
115  beq  memcopy_overlapped_non_optim
116
117  // Optimized Overlapped - Read 32 bytes
118  sub  r14, r14, #32
119  sub  r12, r12, #32
120  cmp  r12, #31
121  ldmia  r14, {r2-r9}
122
123  // If length is less than 32 then disable optim
124  movls  r0, #0
125
126  cmp  r12, #0
127
128  // Optimized Overlapped - Write 32 bytes
129  sub  r10, r10, #32
130  stmia  r10, {r2-r9}
131
132  // while (length != 0)
133  bne  memcopy_overlapped
134  b   memcopy_end
135
136memcopy_default_non_optim
137  // Byte copy
138  ldrb  r3, [r14], #1
139  sub  r12, r12, #1
140  strb  r3, [r10], #1
141
142memcopy_default
143  cmp  r12, #0
144  beq  memcopy_end
145
146// r10 = dest, r14 = source
147memcopy_default_loop
148  cmp  r0, #0
149  beq  memcopy_default_non_optim
150
151  // Optimized memcopy - Read 32 Bytes
152  sub  r12, r12, #32
153  cmp  r12, #31
154  ldmia  r14!, {r2-r9}
155
156  // If length is less than 32 then disable optim
157  movls  r0, #0
158
159  cmp  r12, #0
160
161  // Optimized memcopy - Write 32 Bytes
162  stmia  r10!, {r2-r9}
163
164  // while (length != 0)
165  bne  memcopy_default_loop
166
167memcopy_end
168  mov  r0, r11
169  ldmfd  sp!, {r4-r11, pc}
170
171  END
172
173