• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#include "EfiBind.h"
22#---------------------------------------------------------------------------
23    .686:
24    #.MODEL flat,C
25    .mmx:
26    .code:
27
28#---------------------------------------------------------------------------
29
30.globl ASM_PFX(EfiCommonLibCopyMem)
31
32#VOID
33#EfiCommonLibCopyMem (
34#  IN VOID   *Destination,
35#  IN VOID   *Source,
36#  IN UINTN  Count
37#  )
38#/*++
39#
40#Routine Description:
41#
42#  Copy Length bytes from Source to Destination.
43#
44#Arguments:
45#
46#  Destination - Target of copy
47#
48#  Source      - Place to copy from
49#
50#  Length      - Number of bytes to copy
51#
52#Returns:
53#
54#  None
55#
56#--*/
57ASM_PFX(EfiCommonLibCopyMem):
58
59  pushl  %ebp
60  movl   %esp, %ebp
61  pushl  %ecx # reserve space for Scratch Local variable UINT64 MmxSave
62  pushl  %ecx
63  pushl  %esi
64  pushl  %edi
65
66  movl  0x10(%ebp), %ecx  # Count
67  movl  0xC(%ebp), %esi  # Source
68  movl  8(%ebp), %edi  # Destination
69
70##First off, make sure we have no overlap. That is to say,
71##   if (Source == Destination)           => do nothing
72##   if (Source + Count <= Destination)   => regular copy
73##   if (Destination + Count <= Source)   => regular copy
74##   otherwise, do a reverse copy
75  movl  %esi, %eax
76  addl  %ecx, %eax                    # Source + Count
77  cmpl  %edi, %eax
78  jbe   _StartByteCopy
79
80  movl  %edi, %eax
81  addl  %ecx, %eax                    # Dest + Count
82  cmpl  %esi, %eax
83  jbe   _StartByteCopy
84
85  cmpl  %edi, %esi
86  je    _CopyMemDone
87  jb    _CopyOverlapped               # too bad -- overlaps
88
89  # Pick up misaligned start bytes to get destination pointer 4-byte aligned
90_StartByteCopy:
91  cmpl  $0, %ecx
92  je    _CopyMemDone                # Count == 0, all done
93  movl  %edi, %edx
94  andb  $3, %dl                     # check lower 2 bits of address
95  testb %dl, %dl
96  je    _CopyBlocks                 # already aligned?
97
98  # Copy a byte
99  movb  (%esi), %al                 # get byte from Source
100  movb  %al, (%edi)                 # write byte to Destination
101  decl   %ecx
102  incl  %edi
103  incl  %esi
104  jmp   _StartByteCopy               # back to top of loop
105
106_CopyBlocks:
107  # Compute how many 64-byte blocks we can clear
108  movl  %ecx, %eax                  # get Count in eax
109  shrl  $6, %eax                    # convert to 64-byte count
110  shll  $6, %eax                    # convert back to bytes
111  subl  %eax, %ecx                  # subtract from the original count
112  shrl  $6, %eax                    # and this is how many 64-byte blocks
113
114  # If no 64-byte blocks, then skip
115  cmpl  $0, %eax
116  je    _CopyRemainingDWords
117
118  # Save mm0 to UINT64 MmxSave
119  movq  %mm0, -8(%ebp)
120
121copymmx:
122
123  movq  %ds:(%esi), %mm0
124  movq  %mm0, %ds:(%edi)
125  movq  %ds:8(%esi), %mm0
126  movq  %mm0, %ds:8(%edi)
127  movq  %ds:16(%esi), %mm0
128  movq  %mm0, %ds:16(%edi)
129  movq  %ds:24(%esi), %mm0
130  movq  %mm0, %ds:24(%edi)
131  movq  %ds:32(%esi), %mm0
132  movq  %mm0, %ds:32(%edi)
133  movq  %ds:40(%esi), %mm0
134  movq  %mm0, %ds:40(%edi)
135  movq  %ds:48(%esi), %mm0
136  movq  %mm0, %ds:48(%edi)
137  movq  %ds:56(%esi), %mm0
138  movq  %mm0, %ds:56(%edi)
139
140  addl  $64, %edi
141  addl  $64, %esi
142  decl  %eax
143  jnz   copymmx
144
145# Restore mm0 from MmxSave
146  movq  -8(%ebp), %mm0
147  emms                                 # Exit MMX Instruction
148
149  # Copy as many DWORDS as possible
150_CopyRemainingDWords:
151  cmpl  $4, %ecx
152  jb    _CopyRemainingBytes
153
154  movl  (%esi), %eax                # get data from Source
155  movl  %eax, (%edi)                # write byte to Destination
156  subl  $4, %ecx                    # decrement Count
157  addl  $4, %esi                    # advance Source pointer
158  addl  $4, %edi                    # advance Destination pointer
159  jmp   _CopyRemainingDWords        # back to top
160
161_CopyRemainingBytes:
162  cmpl  $0, %ecx
163  je    _CopyMemDone
164  movb  (%esi), %al                 # get byte from Source
165  movb  %al, (%edi)                 # write byte to Destination
166  decl   %ecx
167  incl   %esi
168  incl  %edi                     # advance Destination pointer
169  jmp   _CopyRemainingBytes         # back to top of loop
170
171  #
172  # We do this block if the source and destination buffers overlap. To
173  # handle it, copy starting at the end of the source buffer and work
174  # your way back. Since this is the atypical case, this code has not
175  # been optimized, and thus simply copies bytes.
176  #
177_CopyOverlapped:
178
179  # Move the source and destination pointers to the end of the range
180  addl  %ecx, %esi                    # Source + Count
181  decl   %esi
182  addl  %ecx, %edi                    # Dest + Count
183  decl   %edi
184
185_CopyOverlappedLoop:
186  cmpl  $0, %ecx
187  je    _CopyMemDone
188  movb  (%esi), %al                 # get byte from Source
189  movb  %al, (%edi)                 # write byte to Destination
190  decl   %ecx
191  decl   %esi
192  decl  %edi
193  jmp   _CopyOverlappedLoop         # back to top of loop
194
195_CopyMemDone:
196
197  popl  %edi
198  popl  %esi
199  leave
200  ret
201#EfiCommonLibCopyMem ENDP
202
203