- Implement RtlPrefectMemoryNonTemporal. Patch by Patrick Baggett <baggett.patrick...
[reactos.git] / reactos / lib / rtl / i386 / mem_asm.S
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: mem_asm.S
5 * PURPOSE: Memory functions
6 * PROGRAMMERS: Patrick Baggett (baggett.patrick@gmail.com)
7 * Alex Ionescu (alex@relsoft.net)
8 * Magnus Olsen (magnusolsen@greatlord.com)
9 */
10
11 .intel_syntax noprefix
12
13 /* GLOBALS ****************************************************************/
14
15 .globl _RtlZeroMemory@8 // (no bug) (max optimze code)
16 .globl _RtlFillMemoryUlong@12 // (no bug) (max optimze code)
17 .globl _RtlFillMemory@12 // [4] (no bug)
18 .globl _RtlCompareMemoryUlong@12 // [5] (no bug)
19 .globl _RtlCompareMemory@12 // [4] (no bug)
20 .globl @RtlPrefetchMemoryNonTemporal@8
21
22 /* FUNCTIONS ***************************************************************/
23
24 _RtlZeroMemory@8:
25 mov ecx,dword [esp + 8 ] // Length
26 cmp ecx,0// if (Length==0) goto .zero
27 je 3f
28
29 pushad // Save all register on the stack
30 mov edi, dword [esp + (4 + 32)] // Destination
31 xor eax,eax // ZeroFillByte = 0
32
33 // code for take four byte each time it loop
34 mov ebx,ecx // temp_Length = Length
35 shr ecx,2// Length = Length / sizeof(ULONG)
36 jz 1f // if (Length==0) goto .1byte
37
38 shl ecx,2// Length = Length * sizeof(ULONG)
39 sub ebx,ecx // temp_Length = temp_Length - Length//
40 jz 2f // if (temp_Length==0) goto .4byte
41
42 // move 4byte and 1byte
43 shr ecx,2// Length = Length / sizeof(ULONG)
44 cld // clear d flag
45 rep stosd// while (Length!=0) { (ULONG *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 }
46 mov ecx,ebx // Length = temp_Length
47 rep stosb// while (Length!=0) { (UCHAR *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 }
48 popad // restore register
49 ret 8 // return
50
51 // move 1byte
52 1:
53 mov ecx,dword [esp + (12 +32) ] // Length
54 cld // clear d flag
55 rep stosb// while (Length!=0) { (UCHAR *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 }
56 popad // restore register
57 ret 8 // return
58
59 // move 4bytes
60 2:
61 shr ecx,2// Length = Length / sizeof(ULONG)
62 cld // clear d flag
63 rep stosd// while (Length!=0) { (ULONG *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 }
64 popad // restore register
65 3:
66 ret 8 // return
67
68 _RtlFillMemoryUlong@12:
69 mov ecx, dword [esp + 8 ] // Length
70 shr ecx,2// Length = Length / sizeof(ULONG)
71 jz 1f // if (Length==0) goto .zero
72
73 push edi
74 mov edi, dword [esp + (4 + 4)] // Destination
75 mov eax, dword [esp + (12 + 4)] // Fill
76 cld
77 rep stosd// while (Length>0) {Destination[Length-1]=Fill// Length = Length - 1}
78 pop edi
79 1:
80 ret 12
81
82 _RtlFillMemory@12:
83 mov ecx,dword [esp + 8 ] // ecx = Length
84 cmp ecx,0// if (Length==0) goto .zero
85 je 2f
86
87 mov edx, dword [esp + 4] // edx = Destination
88 mov eax, dword [esp + 12] // eax = fill
89 1:
90 mov byte [edx + ecx -1],al // src[Length - 1] = fill
91 dec ecx // Length = Length - 1
92 jnz 1b // if (Length!=0) goto .loop
93 2:
94 ret 12 // return
95
96 _RtlCompareMemoryUlong@12:
97 xor eax,eax
98 mov ecx, dword [esp + 8 ] // ecx = Length
99 shr ecx,2 // Length / sizeof(ULONG)
100 jz 1f // if (Length==0) goto .zero
101
102 push edi// register that does not to be save eax,ecx,edx to
103 push ebx// the stack for protetion
104
105 mov edi, dword [esp + (4 + 8)] // edx = Destination
106 mov eax, dword [esp + (12 + 8)] // ebx = value
107 mov ebx,ecx
108 cld
109 repe scasd
110
111 inc ecx
112 mov eax,ebx
113
114 sub eax,ecx
115 shl eax,2
116
117 pop ebx
118 pop edi
119
120 1:
121 ret 12
122
123 _RtlCompareMemory@12:
124 xor eax,eax // count = 0
125 mov ecx, dword [esp + 12 ] // ecx = Length
126 cmp ecx,0 // if (Length==0) goto .zero
127 je 3f
128
129 push edi// register that does not to be save eax,ecx,edx to
130 push ebx// the stack for protetion
131
132 mov edi, dword [esp + (4 + 8)] // edi = Destination
133 mov edx, dword [esp + (8 + 8)] // edx = Source
134
135 1:
136 mov bl,byte [edi + eax ] // if (src[count]!=des[count]) goto .pop_zero
137 cmp byte [edx + eax ],bl
138 jne 2f
139
140 inc eax // count = count + 1
141 dec ecx // Length = Length - 1
142 jnz 1b // if (Length!=0) goto .loop_1byte
143
144 2:
145 pop ebx // restore regiester
146 pop edi
147 3:
148 ret 12 // return count
149
150
151 @RtlPrefetchMemoryNonTemporal@8:
152 ret /* Overwritten by ntoskrnl/ke/i386/kernel.c if SSE is supported (see Ki386SetProcessorFeatures() ) */
153
154 mov eax, [_Ke386CacheGranularity] // Get cache line size
155
156 // This is fastcall, so ecx = address, edx = size
157 fetch_next_line:
158 prefetchnta byte ptr [ecx] // prefechnta(address)
159 sub edx, eax // count = count - cache_line_size
160 add ecx, eax // address = address + cache_line_size
161 cmp edx, 0 // if(count) <= 0
162 ja fetch_next_line // goto fetch_next_line
163 ret