]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/Ia32/EfiCopyMem.asm
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / EfiCommonLib / Ia32 / EfiCopyMem.asm
1 ;/*++
2 ;
3 ;Copyright (c) 2006, 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 ;---------------------------------------------------------------------------
23 .686
24 .model flat,C
25 .mmx
26 .code
27
28 ;---------------------------------------------------------------------------
29
30 ;VOID
31 ;EfiCommonLibCopyMem (
32 ; IN VOID *Destination,
33 ; IN VOID *Source,
34 ; IN UINTN Count
35 ; )
36 ;/*++
37 ;
38 ;Routine Description:
39 ;
40 ; Copy Length bytes from Source to Destination.
41 ;
42 ;Arguments:
43 ;
44 ; Destination - Target of copy
45 ;
46 ; Source - Place to copy from
47 ;
48 ; Length - Number of bytes to copy
49 ;
50 ;Returns:
51 ;
52 ; None
53 ;
54 ;--*/
55 EfiCommonLibCopyMem PROC
56
57 push ebp
58 mov ebp, esp
59 push ecx ; reserve space for Scratch Local variable UINT64 MmxSave
60 push ecx
61 push esi
62 push edi
63
64 mov ecx, [ebp + 10h] ; Count
65 mov esi, [ebp + 0Ch] ; Source
66 mov edi, [ebp + 8] ; Destination
67
68 ; First off, make sure we have no overlap. That is to say,
69 ; if (Source == Destination) => do nothing
70 ; if (Source + Count <= Destination) => regular copy
71 ; if (Destination + Count <= Source) => regular copy
72 ; otherwise, do a reverse copy
73 mov eax, esi
74 add eax, ecx ; Source + Count
75 cmp eax, edi
76 jbe _StartByteCopy
77
78 mov eax, edi
79 add eax, ecx ; Dest + Count
80 cmp eax, esi
81 jbe _StartByteCopy
82
83 cmp esi, edi
84 je _CopyMemDone
85 jb _CopyOverlapped ; too bad -- overlaps
86
87 ; Pick up misaligned start bytes to get destination pointer 4-byte aligned
88 _StartByteCopy:
89 cmp ecx, 0
90 je _CopyMemDone ; Count == 0, all done
91 mov edx, edi
92 and dl, 3 ; check lower 2 bits of address
93 test dl, dl
94 je SHORT _CopyBlocks ; already aligned?
95
96 ; Copy a byte
97 mov al, BYTE PTR [esi] ; get byte from Source
98 mov BYTE PTR [edi], al ; write byte to Destination
99 dec ecx
100 inc edi
101 inc esi
102 jmp _StartByteCopy ; back to top of loop
103
104 _CopyBlocks:
105 ; Compute how many 64-byte blocks we can clear
106 mov eax, ecx ; get Count in eax
107 shr eax, 6 ; convert to 64-byte count
108 shl eax, 6 ; convert back to bytes
109 sub ecx, eax ; subtract from the original count
110 shr eax, 6 ; and this is how many 64-byte blocks
111
112 ; If no 64-byte blocks, then skip
113 cmp eax, 0
114 je _CopyRemainingDWords
115
116 ; Save mm0 to UINT64 MmxSave
117 movq [ebp - 8], mm0
118
119 copymmx:
120
121 movq mm0, QWORD PTR ds:[esi]
122 movq QWORD PTR ds:[edi], mm0
123 movq mm0, QWORD PTR ds:[esi+8]
124 movq QWORD PTR ds:[edi+8], mm0
125 movq mm0, QWORD PTR ds:[esi+16]
126 movq QWORD PTR ds:[edi+16], mm0
127 movq mm0, QWORD PTR ds:[esi+24]
128 movq QWORD PTR ds:[edi+24], mm0
129 movq mm0, QWORD PTR ds:[esi+32]
130 movq QWORD PTR ds:[edi+32], mm0
131 movq mm0, QWORD PTR ds:[esi+40]
132 movq QWORD PTR ds:[edi+40], mm0
133 movq mm0, QWORD PTR ds:[esi+48]
134 movq QWORD PTR ds:[edi+48], mm0
135 movq mm0, QWORD PTR ds:[esi+56]
136 movq QWORD PTR ds:[edi+56], mm0
137
138 add edi, 64
139 add esi, 64
140 dec eax
141 jnz copymmx
142
143 ; Restore mm0 from MmxSave
144 movq mm0, [ebp - 8]
145 emms ; Exit MMX Instruction
146
147 ; Copy as many DWORDS as possible
148 _CopyRemainingDWords:
149 cmp ecx, 4
150 jb _CopyRemainingBytes
151
152 mov eax, DWORD PTR [esi] ; get data from Source
153 mov DWORD PTR [edi], eax ; write byte to Destination
154 sub ecx, 4 ; decrement Count
155 add esi, 4 ; advance Source pointer
156 add edi, 4 ; advance Destination pointer
157 jmp _CopyRemainingDWords ; back to top
158
159 _CopyRemainingBytes:
160 cmp ecx, 0
161 je _CopyMemDone
162 mov al, BYTE PTR [esi] ; get byte from Source
163 mov BYTE PTR [edi], al ; write byte to Destination
164 dec ecx
165 inc esi
166 inc edi ; advance Destination pointer
167 jmp SHORT _CopyRemainingBytes ; back to top of loop
168
169 ;
170 ; We do this block if the source and destination buffers overlap. To
171 ; handle it, copy starting at the end of the source buffer and work
172 ; your way back. Since this is the atypical case, this code has not
173 ; been optimized, and thus simply copies bytes.
174 ;
175 _CopyOverlapped:
176
177 ; Move the source and destination pointers to the end of the range
178 add esi, ecx ; Source + Count
179 dec esi
180 add edi, ecx ; Dest + Count
181 dec edi
182
183 _CopyOverlappedLoop:
184 cmp ecx, 0
185 je _CopyMemDone
186 mov al, BYTE PTR [esi] ; get byte from Source
187 mov BYTE PTR [edi], al ; write byte to Destination
188 dec ecx
189 dec esi
190 dec edi
191 jmp _CopyOverlappedLoop ; back to top of loop
192
193 _CopyMemDone:
194
195 pop edi
196 pop esi
197 leave
198 ret
199 EfiCommonLibCopyMem ENDP
200 END