summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/Ia32/EfiZeroMem.c
blob: fc9ed7b621464d6efccd04be75ce68698a6e6d42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*++

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:

  EfiZeroMem.c

Abstract:

  This is the code that supports IA32-optimized ZeroMem service

--*/

#include "Tiano.h"

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.

--*/
{
  UINT64 MmxSave;
  __asm {
    mov   ecx, Count
    mov   edi, Buffer

    ; Pick up misaligned start bytes (get pointer 4-byte aligned)
_StartByteZero:
    mov   eax, edi    
    and   al, 3                       ; check lower 2 bits of address
    test  al, al
    je    _ZeroBlocks                 ; already aligned?
    cmp   ecx, 0
    je    _ZeroMemDone

    ; Clear the byte memory location
    mov   BYTE PTR [edi], 0           
    inc    edi

    ; Decrement our count
    dec    ecx
    jmp   _StartByteZero        ; back to top of loop

_ZeroBlocks:

    ; Compute how many 64-byte blocks we can clear 
    mov   edx, ecx
    shr   ecx, 6                      ; convert to 64-byte count
    shl   ecx, 6                      ; convert back to bytes
    sub   edx, ecx                    ; subtract from the original count
    shr   ecx, 6                      ; and this is how many 64-byte blocks

    ; If no 64-byte blocks, then skip 
    cmp    ecx, 0
    je    _ZeroRemaining

    ; Save mm0
    movq  MmxSave, mm0

    pxor  mm0, mm0          ; Clear mm0

_B:
    movq  QWORD PTR ds:[edi], mm0
    movq  QWORD PTR ds:[edi+8], mm0
    movq  QWORD PTR ds:[edi+16], mm0
    movq  QWORD PTR ds:[edi+24], mm0
    movq  QWORD PTR ds:[edi+32], mm0
    movq  QWORD PTR ds:[edi+40], mm0
    movq  QWORD PTR ds:[edi+48], mm0
    movq  QWORD PTR ds:[edi+56], mm0
   
    add    edi, 64
    dec    ecx
    jnz    _B
  
; Restore mm0
    movq  mm0, MmxSave
    emms                                 ; Exit MMX Instruction

_ZeroRemaining:
    ; Zero out as many DWORDS as possible
    mov   ecx, edx
    shr   ecx, 2
    xor   eax, eax

    rep stosd

    ; Zero out remaining as bytes
    mov   ecx, edx
    and   ecx, 03

    rep   stosb
 
_ZeroMemDone:
  }
}