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