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