1b341712e314a6161120c30d41e6308bc6aeb2213qhuang#/*++
2b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
34ea9375a2d02a43671437e0d3d808d85afb30afahhtian#Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
44ea9375a2d02a43671437e0d3d808d85afb30afahhtian#This program and the accompanying materials
5b341712e314a6161120c30d41e6308bc6aeb2213qhuang#are licensed and made available under the terms and conditions of the BSD License
6b341712e314a6161120c30d41e6308bc6aeb2213qhuang#which accompanies this distribution.  The full text of the license may be found at
7b341712e314a6161120c30d41e6308bc6aeb2213qhuang#http://opensource.org/licenses/bsd-license.php
8b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
9b341712e314a6161120c30d41e6308bc6aeb2213qhuang#THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10b341712e314a6161120c30d41e6308bc6aeb2213qhuang#WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
12b341712e314a6161120c30d41e6308bc6aeb2213qhuang#Module Name:
13b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
14b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  EfiCopyMem.c
15b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
16b341712e314a6161120c30d41e6308bc6aeb2213qhuang#Abstract:
17b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
18b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  This is the code that supports IA32-optimized CopyMem service
19b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
20b341712e314a6161120c30d41e6308bc6aeb2213qhuang#--*/
21b341712e314a6161120c30d41e6308bc6aeb2213qhuang#include "EfiBind.h"
22b341712e314a6161120c30d41e6308bc6aeb2213qhuang#---------------------------------------------------------------------------
23b341712e314a6161120c30d41e6308bc6aeb2213qhuang    .686:
24b341712e314a6161120c30d41e6308bc6aeb2213qhuang    #.MODEL flat,C
25b341712e314a6161120c30d41e6308bc6aeb2213qhuang    .mmx:
26b341712e314a6161120c30d41e6308bc6aeb2213qhuang    .code:
27b341712e314a6161120c30d41e6308bc6aeb2213qhuang
28b341712e314a6161120c30d41e6308bc6aeb2213qhuang#---------------------------------------------------------------------------
29b341712e314a6161120c30d41e6308bc6aeb2213qhuang
30b341712e314a6161120c30d41e6308bc6aeb2213qhuang.globl ASM_PFX(EfiCommonLibCopyMem)
31b341712e314a6161120c30d41e6308bc6aeb2213qhuang
32b341712e314a6161120c30d41e6308bc6aeb2213qhuang#VOID
33b341712e314a6161120c30d41e6308bc6aeb2213qhuang#EfiCommonLibCopyMem (
34b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  IN VOID   *Destination,
35b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  IN VOID   *Source,
36b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  IN UINTN  Count
37b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  )
38b341712e314a6161120c30d41e6308bc6aeb2213qhuang#/*++
39b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
40b341712e314a6161120c30d41e6308bc6aeb2213qhuang#Routine Description:
41b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
42b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  Copy Length bytes from Source to Destination.
43b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
44b341712e314a6161120c30d41e6308bc6aeb2213qhuang#Arguments:
45b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
46b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  Destination - Target of copy
47b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
48b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  Source      - Place to copy from
49b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
50b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  Length      - Number of bytes to copy
51b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
52b341712e314a6161120c30d41e6308bc6aeb2213qhuang#Returns:
53b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
54b341712e314a6161120c30d41e6308bc6aeb2213qhuang#  None
55b341712e314a6161120c30d41e6308bc6aeb2213qhuang#
56b341712e314a6161120c30d41e6308bc6aeb2213qhuang#--*/
57b341712e314a6161120c30d41e6308bc6aeb2213qhuangASM_PFX(EfiCommonLibCopyMem):
58b341712e314a6161120c30d41e6308bc6aeb2213qhuang
59b341712e314a6161120c30d41e6308bc6aeb2213qhuang  pushl  %ebp
60b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl   %esp, %ebp
61b341712e314a6161120c30d41e6308bc6aeb2213qhuang  pushl  %ecx # reserve space for Scratch Local variable UINT64 MmxSave
62b341712e314a6161120c30d41e6308bc6aeb2213qhuang  pushl  %ecx
63b341712e314a6161120c30d41e6308bc6aeb2213qhuang  pushl  %esi
64b341712e314a6161120c30d41e6308bc6aeb2213qhuang  pushl  %edi
65b341712e314a6161120c30d41e6308bc6aeb2213qhuang
66b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  0x10(%ebp), %ecx  # Count
67b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  0xC(%ebp), %esi  # Source
68b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  8(%ebp), %edi  # Destination
69b341712e314a6161120c30d41e6308bc6aeb2213qhuang
70b341712e314a6161120c30d41e6308bc6aeb2213qhuang##First off, make sure we have no overlap. That is to say,
71b341712e314a6161120c30d41e6308bc6aeb2213qhuang##   if (Source == Destination)           => do nothing
72b341712e314a6161120c30d41e6308bc6aeb2213qhuang##   if (Source + Count <= Destination)   => regular copy
73b341712e314a6161120c30d41e6308bc6aeb2213qhuang##   if (Destination + Count <= Source)   => regular copy
74b341712e314a6161120c30d41e6308bc6aeb2213qhuang##   otherwise, do a reverse copy
75b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  %esi, %eax
76b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  %ecx, %eax                    # Source + Count
77b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  %edi, %eax
783e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  jbe   _StartByteCopy
79b341712e314a6161120c30d41e6308bc6aeb2213qhuang
80b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  %edi, %eax
81b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  %ecx, %eax                    # Dest + Count
82b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  %esi, %eax
833e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  jbe   _StartByteCopy
84b341712e314a6161120c30d41e6308bc6aeb2213qhuang
85b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  %edi, %esi
86b341712e314a6161120c30d41e6308bc6aeb2213qhuang  je    _CopyMemDone
873e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  jb    _CopyOverlapped               # too bad -- overlaps
88b341712e314a6161120c30d41e6308bc6aeb2213qhuang
89b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # Pick up misaligned start bytes to get destination pointer 4-byte aligned
90b341712e314a6161120c30d41e6308bc6aeb2213qhuang_StartByteCopy:
91b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  $0, %ecx
92b341712e314a6161120c30d41e6308bc6aeb2213qhuang  je    _CopyMemDone                # Count == 0, all done
93b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  %edi, %edx
94b341712e314a6161120c30d41e6308bc6aeb2213qhuang  andb  $3, %dl                     # check lower 2 bits of address
95b341712e314a6161120c30d41e6308bc6aeb2213qhuang  testb %dl, %dl
96b341712e314a6161120c30d41e6308bc6aeb2213qhuang  je    _CopyBlocks                 # already aligned?
97b341712e314a6161120c30d41e6308bc6aeb2213qhuang
98b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # Copy a byte
99b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movb  (%esi), %al                 # get byte from Source
100b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movb  %al, (%edi)                 # write byte to Destination
101b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl   %ecx
102b341712e314a6161120c30d41e6308bc6aeb2213qhuang  incl  %edi
103b341712e314a6161120c30d41e6308bc6aeb2213qhuang  incl  %esi
104b341712e314a6161120c30d41e6308bc6aeb2213qhuang  jmp   _StartByteCopy               # back to top of loop
105b341712e314a6161120c30d41e6308bc6aeb2213qhuang
106b341712e314a6161120c30d41e6308bc6aeb2213qhuang_CopyBlocks:
107b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # Compute how many 64-byte blocks we can clear
108b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  %ecx, %eax                  # get Count in eax
109b341712e314a6161120c30d41e6308bc6aeb2213qhuang  shrl  $6, %eax                    # convert to 64-byte count
110b341712e314a6161120c30d41e6308bc6aeb2213qhuang  shll  $6, %eax                    # convert back to bytes
111b341712e314a6161120c30d41e6308bc6aeb2213qhuang  subl  %eax, %ecx                  # subtract from the original count
112b341712e314a6161120c30d41e6308bc6aeb2213qhuang  shrl  $6, %eax                    # and this is how many 64-byte blocks
113b341712e314a6161120c30d41e6308bc6aeb2213qhuang
114b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # If no 64-byte blocks, then skip
115b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  $0, %eax
116b341712e314a6161120c30d41e6308bc6aeb2213qhuang  je    _CopyRemainingDWords
117b341712e314a6161120c30d41e6308bc6aeb2213qhuang
118b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # Save mm0 to UINT64 MmxSave
119b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, -8(%ebp)
120b341712e314a6161120c30d41e6308bc6aeb2213qhuang
121b341712e314a6161120c30d41e6308bc6aeb2213qhuangcopymmx:
122b341712e314a6161120c30d41e6308bc6aeb2213qhuang
123b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:(%esi), %mm0
124b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:(%edi)
125b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:8(%esi), %mm0
126b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:8(%edi)
127b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:16(%esi), %mm0
128b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:16(%edi)
129b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:24(%esi), %mm0
130b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:24(%edi)
131b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:32(%esi), %mm0
132b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:32(%edi)
133b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:40(%esi), %mm0
134b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:40(%edi)
135b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:48(%esi), %mm0
136b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:48(%edi)
137b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %ds:56(%esi), %mm0
138b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  %mm0, %ds:56(%edi)
139b341712e314a6161120c30d41e6308bc6aeb2213qhuang
140b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  $64, %edi
141b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  $64, %esi
142b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl  %eax
143b341712e314a6161120c30d41e6308bc6aeb2213qhuang  jnz   copymmx
144b341712e314a6161120c30d41e6308bc6aeb2213qhuang
145b341712e314a6161120c30d41e6308bc6aeb2213qhuang# Restore mm0 from MmxSave
146b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movq  -8(%ebp), %mm0
147b341712e314a6161120c30d41e6308bc6aeb2213qhuang  emms                                 # Exit MMX Instruction
148b341712e314a6161120c30d41e6308bc6aeb2213qhuang
149b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # Copy as many DWORDS as possible
150b341712e314a6161120c30d41e6308bc6aeb2213qhuang_CopyRemainingDWords:
151b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  $4, %ecx
152b341712e314a6161120c30d41e6308bc6aeb2213qhuang  jb    _CopyRemainingBytes
153b341712e314a6161120c30d41e6308bc6aeb2213qhuang
154b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  (%esi), %eax                # get data from Source
155b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movl  %eax, (%edi)                # write byte to Destination
156b341712e314a6161120c30d41e6308bc6aeb2213qhuang  subl  $4, %ecx                    # decrement Count
157b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  $4, %esi                    # advance Source pointer
158b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  $4, %edi                    # advance Destination pointer
159b341712e314a6161120c30d41e6308bc6aeb2213qhuang  jmp   _CopyRemainingDWords        # back to top
160b341712e314a6161120c30d41e6308bc6aeb2213qhuang
161b341712e314a6161120c30d41e6308bc6aeb2213qhuang_CopyRemainingBytes:
162b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  $0, %ecx
163b341712e314a6161120c30d41e6308bc6aeb2213qhuang  je    _CopyMemDone
164b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movb  (%esi), %al                 # get byte from Source
165b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movb  %al, (%edi)                 # write byte to Destination
166b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl   %ecx
167b341712e314a6161120c30d41e6308bc6aeb2213qhuang  incl   %esi
168b341712e314a6161120c30d41e6308bc6aeb2213qhuang  incl  %edi                     # advance Destination pointer
169b341712e314a6161120c30d41e6308bc6aeb2213qhuang  jmp   _CopyRemainingBytes         # back to top of loop
170b341712e314a6161120c30d41e6308bc6aeb2213qhuang
171b341712e314a6161120c30d41e6308bc6aeb2213qhuang  #
172b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # We do this block if the source and destination buffers overlap. To
173b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # handle it, copy starting at the end of the source buffer and work
174b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # your way back. Since this is the atypical case, this code has not
175b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # been optimized, and thus simply copies bytes.
176b341712e314a6161120c30d41e6308bc6aeb2213qhuang  #
177b341712e314a6161120c30d41e6308bc6aeb2213qhuang_CopyOverlapped:
178b341712e314a6161120c30d41e6308bc6aeb2213qhuang
179b341712e314a6161120c30d41e6308bc6aeb2213qhuang  # Move the source and destination pointers to the end of the range
180b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  %ecx, %esi                    # Source + Count
181b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl   %esi
182b341712e314a6161120c30d41e6308bc6aeb2213qhuang  addl  %ecx, %edi                    # Dest + Count
183b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl   %edi
184b341712e314a6161120c30d41e6308bc6aeb2213qhuang
185b341712e314a6161120c30d41e6308bc6aeb2213qhuang_CopyOverlappedLoop:
186b341712e314a6161120c30d41e6308bc6aeb2213qhuang  cmpl  $0, %ecx
187b341712e314a6161120c30d41e6308bc6aeb2213qhuang  je    _CopyMemDone
188b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movb  (%esi), %al                 # get byte from Source
189b341712e314a6161120c30d41e6308bc6aeb2213qhuang  movb  %al, (%edi)                 # write byte to Destination
190b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl   %ecx
191b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl   %esi
192b341712e314a6161120c30d41e6308bc6aeb2213qhuang  decl  %edi
193b341712e314a6161120c30d41e6308bc6aeb2213qhuang  jmp   _CopyOverlappedLoop         # back to top of loop
194b341712e314a6161120c30d41e6308bc6aeb2213qhuang
195b341712e314a6161120c30d41e6308bc6aeb2213qhuang_CopyMemDone:
196b341712e314a6161120c30d41e6308bc6aeb2213qhuang
197b341712e314a6161120c30d41e6308bc6aeb2213qhuang  popl  %edi
198b341712e314a6161120c30d41e6308bc6aeb2213qhuang  popl  %esi
199b341712e314a6161120c30d41e6308bc6aeb2213qhuang  leave
200b341712e314a6161120c30d41e6308bc6aeb2213qhuang  ret
201b341712e314a6161120c30d41e6308bc6aeb2213qhuang#EfiCommonLibCopyMem ENDP
202b341712e314a6161120c30d41e6308bc6aeb2213qhuang
203