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