]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/Ia32/EfiCopyMem.asm
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / EfiCommonLib / Ia32 / EfiCopyMem.asm
CommitLineData
478db76b 1;/*++\r
2;\r
4ea9375a
HT
3;Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
4;This program and the accompanying materials \r
478db76b 5;are licensed and made available under the terms and conditions of the BSD License \r
6;which accompanies this distribution. The full text of the license may be found at \r
7;http://opensource.org/licenses/bsd-license.php \r
8; \r
9;THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10;WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11;\r
12;Module Name:\r
13;\r
14; EfiCopyMem.c\r
15;\r
16;Abstract:\r
17;\r
18; This is the code that supports IA32-optimized CopyMem service\r
19;\r
20;--*/\r
21\r
22;---------------------------------------------------------------------------\r
23 .686\r
24 .model flat,C\r
25 .mmx\r
26 .code\r
27\r
28;---------------------------------------------------------------------------\r
29\r
30;VOID\r
31;EfiCommonLibCopyMem (\r
32; IN VOID *Destination,\r
33; IN VOID *Source,\r
34; IN UINTN Count\r
35; )\r
36;/*++\r
37;\r
38;Routine Description:\r
39;\r
40; Copy Length bytes from Source to Destination.\r
41;\r
42;Arguments:\r
43;\r
44; Destination - Target of copy\r
45;\r
46; Source - Place to copy from\r
47;\r
48; Length - Number of bytes to copy\r
49;\r
50;Returns:\r
51;\r
52; None\r
53;\r
54;--*/\r
55EfiCommonLibCopyMem PROC\r
56\r
57 push ebp\r
58 mov ebp, esp\r
59 push ecx ; reserve space for Scratch Local variable UINT64 MmxSave\r
60 push ecx\r
61 push esi\r
62 push edi\r
63 \r
64 mov ecx, [ebp + 10h] ; Count\r
65 mov esi, [ebp + 0Ch] ; Source\r
66 mov edi, [ebp + 8] ; Destination\r
67\r
68 ; First off, make sure we have no overlap. That is to say,\r
69 ; if (Source == Destination) => do nothing\r
70 ; if (Source + Count <= Destination) => regular copy\r
71 ; if (Destination + Count <= Source) => regular copy\r
72 ; otherwise, do a reverse copy\r
73 mov eax, esi\r
74 add eax, ecx ; Source + Count\r
75 cmp eax, edi\r
76 jle _StartByteCopy\r
77\r
78 mov eax, edi\r
79 add eax, ecx ; Dest + Count\r
80 cmp eax, esi\r
81 jle _StartByteCopy\r
82\r
83 cmp esi, edi\r
84 je _CopyMemDone \r
85 jl _CopyOverlapped ; too bad -- overlaps\r
86\r
87 ; Pick up misaligned start bytes to get destination pointer 4-byte aligned\r
88_StartByteCopy:\r
89 cmp ecx, 0\r
90 je _CopyMemDone ; Count == 0, all done\r
91 mov edx, edi\r
92 and dl, 3 ; check lower 2 bits of address\r
93 test dl, dl \r
94 je SHORT _CopyBlocks ; already aligned?\r
95\r
96 ; Copy a byte\r
97 mov al, BYTE PTR [esi] ; get byte from Source\r
98 mov BYTE PTR [edi], al ; write byte to Destination\r
99 dec ecx\r
100 inc edi\r
101 inc esi\r
102 jmp _StartByteCopy ; back to top of loop\r
103\r
104_CopyBlocks:\r
105 ; Compute how many 64-byte blocks we can clear \r
106 mov eax, ecx ; get Count in eax\r
107 shr eax, 6 ; convert to 64-byte count\r
108 shl eax, 6 ; convert back to bytes\r
109 sub ecx, eax ; subtract from the original count\r
110 shr eax, 6 ; and this is how many 64-byte blocks\r
111\r
112 ; If no 64-byte blocks, then skip \r
113 cmp eax, 0\r
114 je _CopyRemainingDWords\r
115\r
116 ; Save mm0 to UINT64 MmxSave\r
117 movq [ebp - 8], mm0\r
118\r
119copymmx:\r
120 \r
121 movq mm0, QWORD PTR ds:[esi]\r
122 movq QWORD PTR ds:[edi], mm0\r
123 movq mm0, QWORD PTR ds:[esi+8]\r
124 movq QWORD PTR ds:[edi+8], mm0\r
125 movq mm0, QWORD PTR ds:[esi+16]\r
126 movq QWORD PTR ds:[edi+16], mm0\r
127 movq mm0, QWORD PTR ds:[esi+24]\r
128 movq QWORD PTR ds:[edi+24], mm0\r
129 movq mm0, QWORD PTR ds:[esi+32]\r
130 movq QWORD PTR ds:[edi+32], mm0\r
131 movq mm0, QWORD PTR ds:[esi+40]\r
132 movq QWORD PTR ds:[edi+40], mm0\r
133 movq mm0, QWORD PTR ds:[esi+48]\r
134 movq QWORD PTR ds:[edi+48], mm0\r
135 movq mm0, QWORD PTR ds:[esi+56]\r
136 movq QWORD PTR ds:[edi+56], mm0\r
137 \r
138 add edi, 64\r
139 add esi, 64\r
140 dec eax\r
141 jnz copymmx\r
142 \r
143; Restore mm0 from MmxSave\r
144 movq mm0, [ebp - 8]\r
145 emms ; Exit MMX Instruction\r
146\r
147 ; Copy as many DWORDS as possible\r
148_CopyRemainingDWords:\r
149 cmp ecx, 4\r
150 jb _CopyRemainingBytes\r
151\r
152 mov eax, DWORD PTR [esi] ; get data from Source\r
153 mov DWORD PTR [edi], eax ; write byte to Destination\r
154 sub ecx, 4 ; decrement Count\r
155 add esi, 4 ; advance Source pointer\r
156 add edi, 4 ; advance Destination pointer\r
157 jmp _CopyRemainingDWords ; back to top\r
158\r
159_CopyRemainingBytes:\r
160 cmp ecx, 0\r
161 je _CopyMemDone\r
162 mov al, BYTE PTR [esi] ; get byte from Source\r
163 mov BYTE PTR [edi], al ; write byte to Destination\r
164 dec ecx\r
165 inc esi\r
166 inc edi ; advance Destination pointer\r
167 jmp SHORT _CopyRemainingBytes ; back to top of loop\r
168\r
169 ;\r
170 ; We do this block if the source and destination buffers overlap. To\r
171 ; handle it, copy starting at the end of the source buffer and work\r
172 ; your way back. Since this is the atypical case, this code has not\r
173 ; been optimized, and thus simply copies bytes.\r
174 ;\r
175_CopyOverlapped:\r
176 \r
177 ; Move the source and destination pointers to the end of the range\r
178 add esi, ecx ; Source + Count\r
179 dec esi\r
180 add edi, ecx ; Dest + Count\r
181 dec edi\r
182\r
183_CopyOverlappedLoop:\r
184 cmp ecx, 0\r
185 je _CopyMemDone\r
186 mov al, BYTE PTR [esi] ; get byte from Source\r
187 mov BYTE PTR [edi], al ; write byte to Destination\r
188 dec ecx\r
189 dec esi\r
190 dec edi\r
191 jmp _CopyOverlappedLoop ; back to top of loop\r
192\r
193_CopyMemDone:\r
194\r
195 pop edi\r
196 pop esi\r
197 leave\r
198 ret\r
199EfiCommonLibCopyMem ENDP\r
200 END\r