• 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
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