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