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;--*/ 55EfiCommonLibCopyMem 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 119copymmx: 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 199EfiCommonLibCopyMem ENDP 200 END 201