1478db76bbe37e93416297d37f146ba76ab296380qwang;/*++
2478db76bbe37e93416297d37f146ba76ab296380qwang;
34ea9375a2d02a43671437e0d3d808d85afb30afahhtian;Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
44ea9375a2d02a43671437e0d3d808d85afb30afahhtian;This program and the accompanying materials                          
5478db76bbe37e93416297d37f146ba76ab296380qwang;are licensed and made available under the terms and conditions of the BSD License         
6478db76bbe37e93416297d37f146ba76ab296380qwang;which accompanies this distribution.  The full text of the license may be found at        
7478db76bbe37e93416297d37f146ba76ab296380qwang;http://opensource.org/licenses/bsd-license.php                                            
8478db76bbe37e93416297d37f146ba76ab296380qwang;                                                                                          
9478db76bbe37e93416297d37f146ba76ab296380qwang;THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
10478db76bbe37e93416297d37f146ba76ab296380qwang;WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
11478db76bbe37e93416297d37f146ba76ab296380qwang;
12478db76bbe37e93416297d37f146ba76ab296380qwang;Module Name:
13478db76bbe37e93416297d37f146ba76ab296380qwang;
14478db76bbe37e93416297d37f146ba76ab296380qwang;  EfiCopyMem.c
15478db76bbe37e93416297d37f146ba76ab296380qwang;
16478db76bbe37e93416297d37f146ba76ab296380qwang;Abstract:
17478db76bbe37e93416297d37f146ba76ab296380qwang;
18478db76bbe37e93416297d37f146ba76ab296380qwang;  This is the code that supports IA32-optimized CopyMem service
19478db76bbe37e93416297d37f146ba76ab296380qwang;
20478db76bbe37e93416297d37f146ba76ab296380qwang;--*/
21478db76bbe37e93416297d37f146ba76ab296380qwang
22478db76bbe37e93416297d37f146ba76ab296380qwang;---------------------------------------------------------------------------
23478db76bbe37e93416297d37f146ba76ab296380qwang    .686
24478db76bbe37e93416297d37f146ba76ab296380qwang    .model  flat,C
25478db76bbe37e93416297d37f146ba76ab296380qwang    .mmx
26478db76bbe37e93416297d37f146ba76ab296380qwang    .code
27478db76bbe37e93416297d37f146ba76ab296380qwang
28478db76bbe37e93416297d37f146ba76ab296380qwang;---------------------------------------------------------------------------
29478db76bbe37e93416297d37f146ba76ab296380qwang
30478db76bbe37e93416297d37f146ba76ab296380qwang;VOID
31478db76bbe37e93416297d37f146ba76ab296380qwang;EfiCommonLibCopyMem (
32478db76bbe37e93416297d37f146ba76ab296380qwang;  IN VOID   *Destination,
33478db76bbe37e93416297d37f146ba76ab296380qwang;  IN VOID   *Source,
34478db76bbe37e93416297d37f146ba76ab296380qwang;  IN UINTN  Count
35478db76bbe37e93416297d37f146ba76ab296380qwang;  )
36478db76bbe37e93416297d37f146ba76ab296380qwang;/*++
37478db76bbe37e93416297d37f146ba76ab296380qwang;
38478db76bbe37e93416297d37f146ba76ab296380qwang;Routine Description:
39478db76bbe37e93416297d37f146ba76ab296380qwang;
40478db76bbe37e93416297d37f146ba76ab296380qwang;  Copy Length bytes from Source to Destination.
41478db76bbe37e93416297d37f146ba76ab296380qwang;
42478db76bbe37e93416297d37f146ba76ab296380qwang;Arguments:
43478db76bbe37e93416297d37f146ba76ab296380qwang;
44478db76bbe37e93416297d37f146ba76ab296380qwang;  Destination - Target of copy
45478db76bbe37e93416297d37f146ba76ab296380qwang;
46478db76bbe37e93416297d37f146ba76ab296380qwang;  Source      - Place to copy from
47478db76bbe37e93416297d37f146ba76ab296380qwang;
48478db76bbe37e93416297d37f146ba76ab296380qwang;  Length      - Number of bytes to copy
49478db76bbe37e93416297d37f146ba76ab296380qwang;
50478db76bbe37e93416297d37f146ba76ab296380qwang;Returns:
51478db76bbe37e93416297d37f146ba76ab296380qwang;
52478db76bbe37e93416297d37f146ba76ab296380qwang;  None
53478db76bbe37e93416297d37f146ba76ab296380qwang;
54478db76bbe37e93416297d37f146ba76ab296380qwang;--*/
55478db76bbe37e93416297d37f146ba76ab296380qwangEfiCommonLibCopyMem PROC
56478db76bbe37e93416297d37f146ba76ab296380qwang
57478db76bbe37e93416297d37f146ba76ab296380qwang  push   ebp
58478db76bbe37e93416297d37f146ba76ab296380qwang  mov    ebp, esp
59478db76bbe37e93416297d37f146ba76ab296380qwang  push   ecx ; reserve space for Scratch Local variable UINT64 MmxSave
60478db76bbe37e93416297d37f146ba76ab296380qwang  push   ecx
61478db76bbe37e93416297d37f146ba76ab296380qwang  push   esi
62478db76bbe37e93416297d37f146ba76ab296380qwang  push   edi
63478db76bbe37e93416297d37f146ba76ab296380qwang  
64478db76bbe37e93416297d37f146ba76ab296380qwang  mov   ecx, [ebp + 10h]  ; Count
65478db76bbe37e93416297d37f146ba76ab296380qwang  mov   esi, [ebp + 0Ch] ; Source
66478db76bbe37e93416297d37f146ba76ab296380qwang  mov   edi, [ebp + 8] ; Destination
67478db76bbe37e93416297d37f146ba76ab296380qwang
68478db76bbe37e93416297d37f146ba76ab296380qwang  ; First off, make sure we have no overlap. That is to say,
69478db76bbe37e93416297d37f146ba76ab296380qwang  ;   if (Source == Destination)           => do nothing
70478db76bbe37e93416297d37f146ba76ab296380qwang  ;   if (Source + Count <= Destination)   => regular copy
71478db76bbe37e93416297d37f146ba76ab296380qwang  ;   if (Destination + Count <= Source)   => regular copy
72478db76bbe37e93416297d37f146ba76ab296380qwang  ;   otherwise, do a reverse copy
73478db76bbe37e93416297d37f146ba76ab296380qwang  mov   eax, esi
74478db76bbe37e93416297d37f146ba76ab296380qwang  add   eax, ecx                      ; Source + Count
75478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   eax, edi
763e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  jbe   _StartByteCopy
77478db76bbe37e93416297d37f146ba76ab296380qwang
78478db76bbe37e93416297d37f146ba76ab296380qwang  mov   eax, edi
79478db76bbe37e93416297d37f146ba76ab296380qwang  add   eax, ecx                      ; Dest + Count
80478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   eax, esi
813e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  jbe   _StartByteCopy
82478db76bbe37e93416297d37f146ba76ab296380qwang
83478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   esi, edi
84478db76bbe37e93416297d37f146ba76ab296380qwang  je    _CopyMemDone         
853e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  jb    _CopyOverlapped               ; too bad -- overlaps
86478db76bbe37e93416297d37f146ba76ab296380qwang
87478db76bbe37e93416297d37f146ba76ab296380qwang  ; Pick up misaligned start bytes to get destination pointer 4-byte aligned
88478db76bbe37e93416297d37f146ba76ab296380qwang_StartByteCopy:
89478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   ecx, 0
90478db76bbe37e93416297d37f146ba76ab296380qwang  je    _CopyMemDone                ; Count == 0, all done
91478db76bbe37e93416297d37f146ba76ab296380qwang  mov   edx, edi
92478db76bbe37e93416297d37f146ba76ab296380qwang  and   dl, 3                       ; check lower 2 bits of address
93478db76bbe37e93416297d37f146ba76ab296380qwang  test  dl, dl          
94478db76bbe37e93416297d37f146ba76ab296380qwang  je    SHORT _CopyBlocks           ; already aligned?
95478db76bbe37e93416297d37f146ba76ab296380qwang
96478db76bbe37e93416297d37f146ba76ab296380qwang  ; Copy a byte
97478db76bbe37e93416297d37f146ba76ab296380qwang  mov   al, BYTE PTR [esi]          ; get byte from Source
98478db76bbe37e93416297d37f146ba76ab296380qwang  mov   BYTE PTR [edi], al          ; write byte to Destination
99478db76bbe37e93416297d37f146ba76ab296380qwang  dec    ecx
100478db76bbe37e93416297d37f146ba76ab296380qwang  inc   edi
101478db76bbe37e93416297d37f146ba76ab296380qwang  inc   esi
102478db76bbe37e93416297d37f146ba76ab296380qwang  jmp   _StartByteCopy               ; back to top of loop
103478db76bbe37e93416297d37f146ba76ab296380qwang
104478db76bbe37e93416297d37f146ba76ab296380qwang_CopyBlocks:
105478db76bbe37e93416297d37f146ba76ab296380qwang  ; Compute how many 64-byte blocks we can clear 
106478db76bbe37e93416297d37f146ba76ab296380qwang  mov   eax, ecx                    ; get Count in eax
107478db76bbe37e93416297d37f146ba76ab296380qwang  shr   eax, 6                      ; convert to 64-byte count
108478db76bbe37e93416297d37f146ba76ab296380qwang  shl   eax, 6                      ; convert back to bytes
109478db76bbe37e93416297d37f146ba76ab296380qwang  sub   ecx, eax                    ; subtract from the original count
110478db76bbe37e93416297d37f146ba76ab296380qwang  shr   eax, 6                      ; and this is how many 64-byte blocks
111478db76bbe37e93416297d37f146ba76ab296380qwang
112478db76bbe37e93416297d37f146ba76ab296380qwang  ; If no 64-byte blocks, then skip 
113478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   eax, 0
114478db76bbe37e93416297d37f146ba76ab296380qwang  je    _CopyRemainingDWords
115478db76bbe37e93416297d37f146ba76ab296380qwang
116478db76bbe37e93416297d37f146ba76ab296380qwang  ; Save mm0 to UINT64 MmxSave
117478db76bbe37e93416297d37f146ba76ab296380qwang  movq  [ebp - 8], mm0
118478db76bbe37e93416297d37f146ba76ab296380qwang
119478db76bbe37e93416297d37f146ba76ab296380qwangcopymmx:
120478db76bbe37e93416297d37f146ba76ab296380qwang  
121478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi]
122478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi], mm0
123478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi+8]
124478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi+8], mm0
125478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi+16]
126478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi+16], mm0
127478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi+24]
128478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi+24], mm0
129478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi+32]
130478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi+32], mm0
131478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi+40]
132478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi+40], mm0
133478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi+48]
134478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi+48], mm0
135478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, QWORD PTR ds:[esi+56]
136478db76bbe37e93416297d37f146ba76ab296380qwang  movq  QWORD PTR ds:[edi+56], mm0
137478db76bbe37e93416297d37f146ba76ab296380qwang  
138478db76bbe37e93416297d37f146ba76ab296380qwang  add   edi, 64
139478db76bbe37e93416297d37f146ba76ab296380qwang  add   esi, 64
140478db76bbe37e93416297d37f146ba76ab296380qwang  dec   eax
141478db76bbe37e93416297d37f146ba76ab296380qwang  jnz   copymmx
142478db76bbe37e93416297d37f146ba76ab296380qwang  
143478db76bbe37e93416297d37f146ba76ab296380qwang; Restore mm0 from MmxSave
144478db76bbe37e93416297d37f146ba76ab296380qwang  movq  mm0, [ebp - 8]
145478db76bbe37e93416297d37f146ba76ab296380qwang  emms                                 ; Exit MMX Instruction
146478db76bbe37e93416297d37f146ba76ab296380qwang
147478db76bbe37e93416297d37f146ba76ab296380qwang  ; Copy as many DWORDS as possible
148478db76bbe37e93416297d37f146ba76ab296380qwang_CopyRemainingDWords:
149478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   ecx, 4
150478db76bbe37e93416297d37f146ba76ab296380qwang  jb    _CopyRemainingBytes
151478db76bbe37e93416297d37f146ba76ab296380qwang
152478db76bbe37e93416297d37f146ba76ab296380qwang  mov   eax, DWORD PTR [esi]        ; get data from Source
153478db76bbe37e93416297d37f146ba76ab296380qwang  mov   DWORD PTR [edi], eax        ; write byte to Destination
154478db76bbe37e93416297d37f146ba76ab296380qwang  sub   ecx, 4                      ; decrement Count
155478db76bbe37e93416297d37f146ba76ab296380qwang  add   esi, 4                      ; advance Source pointer
156478db76bbe37e93416297d37f146ba76ab296380qwang  add   edi, 4                      ; advance Destination pointer
157478db76bbe37e93416297d37f146ba76ab296380qwang  jmp   _CopyRemainingDWords        ; back to top
158478db76bbe37e93416297d37f146ba76ab296380qwang
159478db76bbe37e93416297d37f146ba76ab296380qwang_CopyRemainingBytes:
160478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   ecx, 0
161478db76bbe37e93416297d37f146ba76ab296380qwang  je    _CopyMemDone
162478db76bbe37e93416297d37f146ba76ab296380qwang  mov   al, BYTE PTR [esi]          ; get byte from Source
163478db76bbe37e93416297d37f146ba76ab296380qwang  mov   BYTE PTR [edi], al          ; write byte to Destination
164478db76bbe37e93416297d37f146ba76ab296380qwang  dec    ecx
165478db76bbe37e93416297d37f146ba76ab296380qwang  inc    esi
166478db76bbe37e93416297d37f146ba76ab296380qwang  inc   edi                      ; advance Destination pointer
167478db76bbe37e93416297d37f146ba76ab296380qwang  jmp   SHORT _CopyRemainingBytes   ; back to top of loop
168478db76bbe37e93416297d37f146ba76ab296380qwang
169478db76bbe37e93416297d37f146ba76ab296380qwang  ;
170478db76bbe37e93416297d37f146ba76ab296380qwang  ; We do this block if the source and destination buffers overlap. To
171478db76bbe37e93416297d37f146ba76ab296380qwang  ; handle it, copy starting at the end of the source buffer and work
172478db76bbe37e93416297d37f146ba76ab296380qwang  ; your way back. Since this is the atypical case, this code has not
173478db76bbe37e93416297d37f146ba76ab296380qwang  ; been optimized, and thus simply copies bytes.
174478db76bbe37e93416297d37f146ba76ab296380qwang  ;
175478db76bbe37e93416297d37f146ba76ab296380qwang_CopyOverlapped:
176478db76bbe37e93416297d37f146ba76ab296380qwang   
177478db76bbe37e93416297d37f146ba76ab296380qwang  ; Move the source and destination pointers to the end of the range
178478db76bbe37e93416297d37f146ba76ab296380qwang  add   esi, ecx                      ; Source + Count
179478db76bbe37e93416297d37f146ba76ab296380qwang  dec    esi
180478db76bbe37e93416297d37f146ba76ab296380qwang  add   edi, ecx                      ; Dest + Count
181478db76bbe37e93416297d37f146ba76ab296380qwang  dec    edi
182478db76bbe37e93416297d37f146ba76ab296380qwang
183478db76bbe37e93416297d37f146ba76ab296380qwang_CopyOverlappedLoop:
184478db76bbe37e93416297d37f146ba76ab296380qwang  cmp   ecx, 0
185478db76bbe37e93416297d37f146ba76ab296380qwang  je    _CopyMemDone
186478db76bbe37e93416297d37f146ba76ab296380qwang  mov   al, BYTE PTR [esi]          ; get byte from Source
187478db76bbe37e93416297d37f146ba76ab296380qwang  mov   BYTE PTR [edi], al          ; write byte to Destination
188478db76bbe37e93416297d37f146ba76ab296380qwang  dec    ecx
189478db76bbe37e93416297d37f146ba76ab296380qwang  dec    esi
190478db76bbe37e93416297d37f146ba76ab296380qwang  dec   edi
191478db76bbe37e93416297d37f146ba76ab296380qwang  jmp   _CopyOverlappedLoop         ; back to top of loop
192478db76bbe37e93416297d37f146ba76ab296380qwang
193478db76bbe37e93416297d37f146ba76ab296380qwang_CopyMemDone:
194478db76bbe37e93416297d37f146ba76ab296380qwang
195478db76bbe37e93416297d37f146ba76ab296380qwang  pop   edi
196478db76bbe37e93416297d37f146ba76ab296380qwang  pop   esi
197478db76bbe37e93416297d37f146ba76ab296380qwang  leave
198478db76bbe37e93416297d37f146ba76ab296380qwang  ret
199478db76bbe37e93416297d37f146ba76ab296380qwangEfiCommonLibCopyMem ENDP
200478db76bbe37e93416297d37f146ba76ab296380qwang	END
201