+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- EfiCopyMem.c\r
-\r
-Abstract:\r
-\r
- This is the code that supports IA32-optimized CopyMem service\r
-\r
---*/\r
-\r
-#include "Tiano.h"\r
-\r
-VOID\r
-EfiCommonLibCopyMem (\r
- IN VOID *Destination,\r
- IN VOID *Source,\r
- IN UINTN Count\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Copy Length bytes from Source to Destination.\r
-\r
-Arguments:\r
-\r
- Destination - Target of copy\r
-\r
- Source - Place to copy from\r
-\r
- Length - Number of bytes to copy\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- UINT64 MmxSave;\r
- __asm {\r
- \r
- mov ecx, Count\r
- mov esi, Source\r
- mov edi, Destination\r
-\r
- ; First off, make sure we have no overlap. That is to say,\r
- ; if (Source == Destination) => do nothing\r
- ; if (Source + Count <= Destination) => regular copy\r
- ; if (Destination + Count <= Source) => regular copy\r
- ; if (Source >= Destination) => regular copy\r
- ; otherwise, do a reverse copy\r
- mov eax, esi\r
- add eax, ecx ; Source + Count\r
- cmp eax, edi\r
- jbe _StartByteCopy\r
-\r
- mov eax, edi\r
- add eax, ecx ; Dest + Count\r
- cmp eax, esi\r
- jbe _StartByteCopy\r
-\r
- cmp esi, edi\r
- je _CopyMemDone \r
- jb _CopyOverlapped ; too bad -- overlaps\r
-\r
- ; Pick up misaligned start bytes to get destination pointer 4-byte aligned\r
-_StartByteCopy:\r
- cmp ecx, 0\r
- je _CopyMemDone ; Count == 0, all done\r
- mov edx, edi\r
- and dl, 3 ; check lower 2 bits of address\r
- test dl, dl \r
- je SHORT _CopyBlocks ; already aligned?\r
-\r
- ; Copy a byte\r
- mov al, BYTE PTR [esi] ; get byte from Source\r
- mov BYTE PTR [edi], al ; write byte to Destination\r
- dec ecx\r
- inc edi\r
- inc esi\r
- jmp _StartByteCopy ; back to top of loop\r
-\r
-_CopyBlocks:\r
- ; Compute how many 64-byte blocks we can clear \r
- mov eax, ecx ; get Count in eax\r
- shr eax, 6 ; convert to 64-byte count\r
- shl eax, 6 ; convert back to bytes\r
- sub ecx, eax ; subtract from the original count\r
- shr eax, 6 ; and this is how many 64-byte blocks\r
-\r
- ; If no 64-byte blocks, then skip \r
- cmp eax, 0\r
- je _CopyRemainingDWords\r
-\r
- ; Save mm0\r
- movq MmxSave, mm0\r
-\r
-copymmx:\r
- \r
- movq mm0, QWORD PTR ds:[esi]\r
- movq QWORD PTR ds:[edi], mm0\r
- movq mm0, QWORD PTR ds:[esi+8]\r
- movq QWORD PTR ds:[edi+8], mm0\r
- movq mm0, QWORD PTR ds:[esi+16]\r
- movq QWORD PTR ds:[edi+16], mm0\r
- movq mm0, QWORD PTR ds:[esi+24]\r
- movq QWORD PTR ds:[edi+24], mm0\r
- movq mm0, QWORD PTR ds:[esi+32]\r
- movq QWORD PTR ds:[edi+32], mm0\r
- movq mm0, QWORD PTR ds:[esi+40]\r
- movq QWORD PTR ds:[edi+40], mm0\r
- movq mm0, QWORD PTR ds:[esi+48]\r
- movq QWORD PTR ds:[edi+48], mm0\r
- movq mm0, QWORD PTR ds:[esi+56]\r
- movq QWORD PTR ds:[edi+56], mm0\r
- \r
- add edi, 64\r
- add esi, 64\r
- dec eax\r
- jnz copymmx\r
- \r
-; Restore mm0\r
- movq mm0, MmxSave\r
- emms ; Exit MMX Instruction\r
-\r
- ; Copy as many DWORDS as possible\r
-_CopyRemainingDWords:\r
- cmp ecx, 4\r
- jb _CopyRemainingBytes\r
-\r
- mov eax, DWORD PTR [esi] ; get data from Source\r
- mov DWORD PTR [edi], eax ; write byte to Destination\r
- sub ecx, 4 ; decrement Count\r
- add esi, 4 ; advance Source pointer\r
- add edi, 4 ; advance Destination pointer\r
- jmp _CopyRemainingDWords ; back to top\r
-\r
-_CopyRemainingBytes:\r
- cmp ecx, 0\r
- je _CopyMemDone\r
- mov al, BYTE PTR [esi] ; get byte from Source\r
- mov BYTE PTR [edi], al ; write byte to Destination\r
- dec ecx\r
- inc esi\r
- inc edi ; advance Destination pointer\r
- jmp SHORT _CopyRemainingBytes ; back to top of loop\r
-\r
- ;\r
- ; We do this block if the source and destination buffers overlap. To\r
- ; handle it, copy starting at the end of the source buffer and work\r
- ; your way back. Since this is the atypical case, this code has not\r
- ; been optimized, and thus simply copies bytes.\r
- ;\r
-_CopyOverlapped:\r
- \r
- ; Move the source and destination pointers to the end of the range\r
- add esi, ecx ; Source + Count\r
- dec esi\r
- add edi, ecx ; Dest + Count\r
- dec edi\r
-\r
-_CopyOverlappedLoop:\r
- cmp ecx, 0\r
- je _CopyMemDone\r
- mov al, BYTE PTR [esi] ; get byte from Source\r
- mov BYTE PTR [edi], al ; write byte to Destination\r
- dec ecx\r
- dec esi\r
- dec edi\r
- jmp _CopyOverlappedLoop ; back to top of loop\r
-\r
-_CopyMemDone:\r
- }\r
-}\r