Add in .S file for GCC tool-chain.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5537 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
#/*++
|
||||
#
|
||||
#Copyright (c) 2006, Intel Corporation
|
||||
#All rights reserved. This program and the accompanying materials
|
||||
#are licensed and made available under the terms and conditions of the BSD License
|
||||
#which accompanies this distribution. The full text of the license may be found at
|
||||
#http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
#THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
#WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#Module Name:
|
||||
#
|
||||
# EfiCopyMem.c
|
||||
#
|
||||
#Abstract:
|
||||
#
|
||||
# This is the code that supports IA32-optimized CopyMem service
|
||||
#
|
||||
#--*/
|
||||
#include "EfiBind.h"
|
||||
#---------------------------------------------------------------------------
|
||||
.686:
|
||||
#.MODEL flat,C
|
||||
.mmx:
|
||||
.code:
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
.globl ASM_PFX(EfiCommonLibCopyMem)
|
||||
|
||||
#VOID
|
||||
#EfiCommonLibCopyMem (
|
||||
# IN VOID *Destination,
|
||||
# IN VOID *Source,
|
||||
# IN UINTN Count
|
||||
# )
|
||||
#/*++
|
||||
#
|
||||
#Routine Description:
|
||||
#
|
||||
# Copy Length bytes from Source to Destination.
|
||||
#
|
||||
#Arguments:
|
||||
#
|
||||
# Destination - Target of copy
|
||||
#
|
||||
# Source - Place to copy from
|
||||
#
|
||||
# Length - Number of bytes to copy
|
||||
#
|
||||
#Returns:
|
||||
#
|
||||
# None
|
||||
#
|
||||
#--*/
|
||||
ASM_PFX(EfiCommonLibCopyMem):
|
||||
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %ecx # reserve space for Scratch Local variable UINT64 MmxSave
|
||||
pushl %ecx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
|
||||
movl 0x10(%ebp), %ecx # Count
|
||||
movl 0xC(%ebp), %esi # Source
|
||||
movl 8(%ebp), %edi # Destination
|
||||
|
||||
##First off, make sure we have no overlap. That is to say,
|
||||
## if (Source == Destination) => do nothing
|
||||
## if (Source + Count <= Destination) => regular copy
|
||||
## if (Destination + Count <= Source) => regular copy
|
||||
## otherwise, do a reverse copy
|
||||
movl %esi, %eax
|
||||
addl %ecx, %eax # Source + Count
|
||||
cmpl %edi, %eax
|
||||
jle _StartByteCopy
|
||||
|
||||
movl %edi, %eax
|
||||
addl %ecx, %eax # Dest + Count
|
||||
cmpl %esi, %eax
|
||||
jle _StartByteCopy
|
||||
|
||||
cmpl %edi, %esi
|
||||
je _CopyMemDone
|
||||
jl _CopyOverlapped # too bad -- overlaps
|
||||
|
||||
# Pick up misaligned start bytes to get destination pointer 4-byte aligned
|
||||
_StartByteCopy:
|
||||
cmpl $0, %ecx
|
||||
je _CopyMemDone # Count == 0, all done
|
||||
movl %edi, %edx
|
||||
andb $3, %dl # check lower 2 bits of address
|
||||
testb %dl, %dl
|
||||
je _CopyBlocks # already aligned?
|
||||
|
||||
# Copy a byte
|
||||
movb (%esi), %al # get byte from Source
|
||||
movb %al, (%edi) # write byte to Destination
|
||||
decl %ecx
|
||||
incl %edi
|
||||
incl %esi
|
||||
jmp _StartByteCopy # back to top of loop
|
||||
|
||||
_CopyBlocks:
|
||||
# Compute how many 64-byte blocks we can clear
|
||||
movl %ecx, %eax # get Count in eax
|
||||
shrl $6, %eax # convert to 64-byte count
|
||||
shll $6, %eax # convert back to bytes
|
||||
subl %eax, %ecx # subtract from the original count
|
||||
shrl $6, %eax # and this is how many 64-byte blocks
|
||||
|
||||
# If no 64-byte blocks, then skip
|
||||
cmpl $0, %eax
|
||||
je _CopyRemainingDWords
|
||||
|
||||
# Save mm0 to UINT64 MmxSave
|
||||
movq %mm0, -8(%ebp)
|
||||
|
||||
copymmx:
|
||||
|
||||
movq %ds:(%esi), %mm0
|
||||
movq %mm0, %ds:(%edi)
|
||||
movq %ds:8(%esi), %mm0
|
||||
movq %mm0, %ds:8(%edi)
|
||||
movq %ds:16(%esi), %mm0
|
||||
movq %mm0, %ds:16(%edi)
|
||||
movq %ds:24(%esi), %mm0
|
||||
movq %mm0, %ds:24(%edi)
|
||||
movq %ds:32(%esi), %mm0
|
||||
movq %mm0, %ds:32(%edi)
|
||||
movq %ds:40(%esi), %mm0
|
||||
movq %mm0, %ds:40(%edi)
|
||||
movq %ds:48(%esi), %mm0
|
||||
movq %mm0, %ds:48(%edi)
|
||||
movq %ds:56(%esi), %mm0
|
||||
movq %mm0, %ds:56(%edi)
|
||||
|
||||
addl $64, %edi
|
||||
addl $64, %esi
|
||||
decl %eax
|
||||
jnz copymmx
|
||||
|
||||
# Restore mm0 from MmxSave
|
||||
movq -8(%ebp), %mm0
|
||||
emms # Exit MMX Instruction
|
||||
|
||||
# Copy as many DWORDS as possible
|
||||
_CopyRemainingDWords:
|
||||
cmpl $4, %ecx
|
||||
jb _CopyRemainingBytes
|
||||
|
||||
movl (%esi), %eax # get data from Source
|
||||
movl %eax, (%edi) # write byte to Destination
|
||||
subl $4, %ecx # decrement Count
|
||||
addl $4, %esi # advance Source pointer
|
||||
addl $4, %edi # advance Destination pointer
|
||||
jmp _CopyRemainingDWords # back to top
|
||||
|
||||
_CopyRemainingBytes:
|
||||
cmpl $0, %ecx
|
||||
je _CopyMemDone
|
||||
movb (%esi), %al # get byte from Source
|
||||
movb %al, (%edi) # write byte to Destination
|
||||
decl %ecx
|
||||
incl %esi
|
||||
incl %edi # advance Destination pointer
|
||||
jmp _CopyRemainingBytes # back to top of loop
|
||||
|
||||
#
|
||||
# We do this block if the source and destination buffers overlap. To
|
||||
# handle it, copy starting at the end of the source buffer and work
|
||||
# your way back. Since this is the atypical case, this code has not
|
||||
# been optimized, and thus simply copies bytes.
|
||||
#
|
||||
_CopyOverlapped:
|
||||
|
||||
# Move the source and destination pointers to the end of the range
|
||||
addl %ecx, %esi # Source + Count
|
||||
decl %esi
|
||||
addl %ecx, %edi # Dest + Count
|
||||
decl %edi
|
||||
|
||||
_CopyOverlappedLoop:
|
||||
cmpl $0, %ecx
|
||||
je _CopyMemDone
|
||||
movb (%esi), %al # get byte from Source
|
||||
movb %al, (%edi) # write byte to Destination
|
||||
decl %ecx
|
||||
decl %esi
|
||||
decl %edi
|
||||
jmp _CopyOverlappedLoop # back to top of loop
|
||||
|
||||
_CopyMemDone:
|
||||
|
||||
popl %edi
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
#EfiCommonLibCopyMem ENDP
|
||||
|
Reference in New Issue
Block a user