]>
Commit | Line | Data |
---|---|---|
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 | |
57 | ASM_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 | |
121 | copymmx: \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 |