| #/*++ | |
| # | |
| #Copyright (c) 2006, Intel Corporation. All rights reserved.<BR> | |
| #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: | |
| # | |
| # EfiZeroMem.c | |
| # | |
| #Abstract: | |
| # | |
| # This is the code that supports IA32-optimized ZeroMem service | |
| # | |
| #--*/ | |
| #include "EfiBind.h" | |
| #--------------------------------------------------------------------------- | |
| .686: | |
| #.MODEL flat,C | |
| .mmx: | |
| .code: | |
| #--------------------------------------------------------------------------- | |
| .globl ASM_PFX(EfiCommonLibZeroMem) | |
| #VOID | |
| #EfiCommonLibZeroMem ( | |
| # IN VOID *Buffer, | |
| # IN UINTN Count | |
| # ) | |
| #/*++ | |
| # | |
| #Input: VOID *Buffer - Pointer to buffer to clear | |
| # UINTN Count - Number of bytes to clear | |
| # | |
| #Output: None. | |
| # | |
| #Saves: | |
| # | |
| #Modifies: | |
| # | |
| #Description: This function is an optimized zero-memory function. | |
| # | |
| #Notes: This function tries to zero memory 8 bytes at a time. As a result, | |
| # it first picks up any misaligned bytes, then words, before getting | |
| # in the main loop that does the 8-byte clears. | |
| # | |
| #--*/ | |
| ASM_PFX(EfiCommonLibZeroMem): | |
| # UINT64 MmxSave; | |
| pushl %ebp | |
| movl %esp, %ebp | |
| pushl %ecx # Reserve space for local variable MmxSave | |
| pushl %ecx | |
| pushl %edi | |
| movl 0xC(%ebp), %ecx # Count | |
| movl 8(%ebp), %edi # Buffer | |
| # Pick up misaligned start bytes (get pointer 4-byte aligned) | |
| _StartByteZero: | |
| movl %edi, %eax | |
| andb $3, %al # check lower 2 bits of address | |
| testb %al, %al | |
| je _ZeroBlocks # already aligned? | |
| cmpl $0, %ecx | |
| je _ZeroMemDone | |
| # Clear the byte memory location | |
| movb $0, (%edi) | |
| incl %edi | |
| # Decrement our count | |
| decl %ecx | |
| jmp _StartByteZero # back to top of loop | |
| _ZeroBlocks: | |
| # Compute how many 64-byte blocks we can clear | |
| movl %ecx, %edx | |
| shrl $6, %ecx # convert to 64-byte count | |
| shll $6, %ecx # convert back to bytes | |
| subl %ecx, %edx # subtract from the original count | |
| shrl $6, %ecx # and this is how many 64-byte blocks | |
| # If no 64-byte blocks, then skip | |
| cmpl $0, %ecx | |
| je _ZeroRemaining | |
| # Save mm0 | |
| movq %mm0, -8(%ebp) # Save mm0 to MmxSave | |
| pxor %mm0, %mm0 # Clear mm0 | |
| _B: | |
| movq %mm0, %ds:(%edi) | |
| movq %mm0, %ds:8(%edi) | |
| movq %mm0, %ds:16(%edi) | |
| movq %mm0, %ds:24(%edi) | |
| movq %mm0, %ds:32(%edi) | |
| movq %mm0, %ds:40(%edi) | |
| movq %mm0, %ds:48(%edi) | |
| movq %mm0, %ds:56(%edi) | |
| addl $64, %edi | |
| decl %ecx | |
| jnz _B | |
| # Restore mm0 | |
| movq -8(%ebp), %mm0 # Restore mm0 from MmxSave | |
| emms # Exit MMX Instruction | |
| _ZeroRemaining: | |
| # Zero out as many DWORDS as possible | |
| movl %edx, %ecx | |
| shrl $2, %ecx | |
| xorl %eax, %eax | |
| rep | |
| stosl | |
| # Zero out remaining as bytes | |
| movl %edx, %ecx | |
| andl $03, %ecx | |
| rep | |
| stosb | |
| _ZeroMemDone: | |
| popl %edi | |
| leave | |
| ret | |
| #EfiCommonLibZeroMem ENDP | |