]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/Ia32/EfiCopyMem.c
8ef88513c8064dea9cbf8ad7fbd77140feb68e20
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / EfiCommonLib / Ia32 / EfiCopyMem.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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 ; otherwise, do a reverse copy
62 mov eax, esi
63 add eax, ecx ; Source + Count
64 cmp eax, edi
65 jle _StartByteCopy
66
67 mov eax, edi
68 add eax, ecx ; Dest + Count
69 cmp eax, esi
70 jle _StartByteCopy
71
72 cmp esi, edi
73 je _CopyMemDone
74 jl _CopyOverlapped ; too bad -- overlaps
75
76 ; Pick up misaligned start bytes to get destination pointer 4-byte aligned
77 _StartByteCopy:
78 cmp ecx, 0
79 je _CopyMemDone ; Count == 0, all done
80 mov edx, edi
81 and dl, 3 ; check lower 2 bits of address
82 test dl, dl
83 je SHORT _CopyBlocks ; already aligned?
84
85 ; Copy a byte
86 mov al, BYTE PTR [esi] ; get byte from Source
87 mov BYTE PTR [edi], al ; write byte to Destination
88 dec ecx
89 inc edi
90 inc esi
91 jmp _StartByteCopy ; back to top of loop
92
93 _CopyBlocks:
94 ; Compute how many 64-byte blocks we can clear
95 mov eax, ecx ; get Count in eax
96 shr eax, 6 ; convert to 64-byte count
97 shl eax, 6 ; convert back to bytes
98 sub ecx, eax ; subtract from the original count
99 shr eax, 6 ; and this is how many 64-byte blocks
100
101 ; If no 64-byte blocks, then skip
102 cmp eax, 0
103 je _CopyRemainingDWords
104
105 ; Save mm0
106 movq MmxSave, mm0
107
108 copymmx:
109
110 movq mm0, QWORD PTR ds:[esi]
111 movq QWORD PTR ds:[edi], mm0
112 movq mm0, QWORD PTR ds:[esi+8]
113 movq QWORD PTR ds:[edi+8], mm0
114 movq mm0, QWORD PTR ds:[esi+16]
115 movq QWORD PTR ds:[edi+16], mm0
116 movq mm0, QWORD PTR ds:[esi+24]
117 movq QWORD PTR ds:[edi+24], mm0
118 movq mm0, QWORD PTR ds:[esi+32]
119 movq QWORD PTR ds:[edi+32], mm0
120 movq mm0, QWORD PTR ds:[esi+40]
121 movq QWORD PTR ds:[edi+40], mm0
122 movq mm0, QWORD PTR ds:[esi+48]
123 movq QWORD PTR ds:[edi+48], mm0
124 movq mm0, QWORD PTR ds:[esi+56]
125 movq QWORD PTR ds:[edi+56], mm0
126
127 add edi, 64
128 add esi, 64
129 dec eax
130 jnz copymmx
131
132 ; Restore mm0
133 movq mm0, MmxSave
134 emms ; Exit MMX Instruction
135
136 ; Copy as many DWORDS as possible
137 _CopyRemainingDWords:
138 cmp ecx, 4
139 jb _CopyRemainingBytes
140
141 mov eax, DWORD PTR [esi] ; get data from Source
142 mov DWORD PTR [edi], eax ; write byte to Destination
143 sub ecx, 4 ; decrement Count
144 add esi, 4 ; advance Source pointer
145 add edi, 4 ; advance Destination pointer
146 jmp _CopyRemainingDWords ; back to top
147
148 _CopyRemainingBytes:
149 cmp ecx, 0
150 je _CopyMemDone
151 mov al, BYTE PTR [esi] ; get byte from Source
152 mov BYTE PTR [edi], al ; write byte to Destination
153 dec ecx
154 inc esi
155 inc edi ; advance Destination pointer
156 jmp SHORT _CopyRemainingBytes ; back to top of loop
157
158 ;
159 ; We do this block if the source and destination buffers overlap. To
160 ; handle it, copy starting at the end of the source buffer and work
161 ; your way back. Since this is the atypical case, this code has not
162 ; been optimized, and thus simply copies bytes.
163 ;
164 _CopyOverlapped:
165
166 ; Move the source and destination pointers to the end of the range
167 add esi, ecx ; Source + Count
168 dec esi
169 add edi, ecx ; Dest + Count
170 dec edi
171
172 _CopyOverlappedLoop:
173 cmp ecx, 0
174 je _CopyMemDone
175 mov al, BYTE PTR [esi] ; get byte from Source
176 mov BYTE PTR [edi], al ; write byte to Destination
177 dec ecx
178 dec esi
179 dec edi
180 jmp _CopyOverlappedLoop ; back to top of loop
181
182 _CopyMemDone:
183 }
184 }