[AMD64]
[reactos.git] / reactos / lib / rtl / amd64 / slist.S
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/amd64/interlck.S
5 * PURPOSE: Rtl Interlocked Functions for amd64
6 * PROGRAMMERS: Timo Kreuzer
7 */
8
9 #include <reactos/asm.h>
10 #include <ndk/amd64/asm.h>
11
12 #define SLIST8A_DEPTH_MASK 0x000000000000FFFF
13 #define SLIST8A_DEPTH_INC 0x0000000000000001
14 #define SLIST8A_SEQUENCE_MASK 0x0000000001FF0000
15 #define SLIST8A_SEQUENCE_INC 0x0000000000010000
16 #define SLIST8A_NEXTENTRY_MASK 0xFFFFFFFFFE000000
17 #define SLIST8A_NEXTENTRY_SHIFT 21
18 #define SLIST8B_HEADERTYPE_MASK 0x0000000000000001
19 #define SLIST8B_INIT_MASK 0x0000000000000002
20 #define SLIST8B_REGION_MASK 0xE000000000000000
21 #define SLIST8_POINTER_MASK 0x000007FFFFFFFFF0
22
23 #define SLIST16A_DEPTH_MASK 0x000000000000FFFF
24 #define SLIST16A_DEPTH_INC 0x0000000000000001
25 #define SLIST16A_SEQUENCE_MASK 0xFFFFFFFFFFFF0000
26 #define SLIST16A_SEQUENCE_INC 0x0000000000010000
27 #define SLIST16B_HEADERTYPE_MASK 0x0000000000000001
28 #define SLIST16B_INIT_MASK 0x0000000000000002
29 #define SLIST16B_NEXTENTY_MASK 0xFFFFFFFFFFFFFFF0
30
31
32 /* FUNCTIONS ****************************************************************/
33
34 .global ExpInterlockedPopEntrySList
35 .global ExpInterlockedPopEntrySListResume
36 .global ExpInterlockedPopEntrySListFault
37 .global ExpInterlockedPopEntrySListEnd
38 .global ExpInterlockedPopEntrySListResume16
39 .global ExpInterlockedPopEntrySListFault16
40 .global ExpInterlockedPopEntrySListEnd16
41 .global ExpInterlockedPushEntrySList
42 .global ExpInterlockedFlushSList
43
44 /* PSLIST_ENTRY
45 * NTAPI
46 * RtlInterlockedPopEntrySList(
47 * IN PSLIST_HEADER ListHead);
48 */
49 .proc RtlInterlockedPopEntrySList
50 ExpInterlockedPopEntrySList:
51
52 /* Load ListHead->Region into rdx */
53 mov rdx, [rcx + 8]
54
55 /* Load ListHead->Alignment into rax */
56 mov rax, [rcx]
57
58 /* Check what kind of header this is */
59 test rdx, SLIST8B_HEADERTYPE_MASK
60 jnz RtlInterlockedPopEntrySList16
61
62 /* We have an 8 byte header */
63
64 ExpInterlockedPopEntrySListResume:
65
66 /* Check if ListHead->NextEntry is NULL */
67 mov r9, rax
68 and r9, SLIST8A_NEXTENTRY_MASK
69 jz RtlInterlockedPopEntrySListEmpty
70
71 /* Copy Depth and Sequence number and adjust Depth */
72 lea r8, [rax - SLIST8A_DEPTH_INC]
73 and r8, SLIST8A_SEQUENCE_MASK | SLIST8A_DEPTH_MASK
74
75 /* Create a pointer template from rcx in rdx */
76 mov rdx, ~SLIST8_POINTER_MASK
77 and rdx, rcx
78
79 /* Shift the NextEntry pointer */
80 shr r9, SLIST8A_NEXTENTRY_SHIFT
81
82 /* Combine to new pointer in rdx */
83 or rdx, r9
84
85 ExpInterlockedPopEntrySListFault:
86
87 /* Load the next NextEntry pointer to r9 */
88 mov r9, [rdx]
89
90 /* Shift bits in place */
91 shl r9, SLIST8A_NEXTENTRY_SHIFT
92
93 /* Combine into r8 */
94 or r8, r9
95
96 ExpInterlockedPopEntrySListEnd:
97
98 /* If [rcx] equals rax, exchange it with r8 */
99 lock cmpxchg [rcx], r8
100
101 /* If not equal, retry with rax, being the content of [rcx] now */
102 jnz ExpInterlockedPopEntrySListResume
103
104 /* Shift the pointer bits in place */
105 and rax, SLIST8A_NEXTENTRY_MASK
106 shr rax, SLIST8A_NEXTENTRY_SHIFT
107
108 /* Use rcx as pointer template */
109 mov rdx, ~SLIST8_POINTER_MASK
110 and rdx, rcx
111
112 /* Combine result and return */
113 or rax, rdx
114 ret
115
116 RtlInterlockedPopEntrySListEmpty:
117 xor rax, rax
118 ret
119
120 RtlInterlockedPopEntrySList16:
121 /* This is a 16 byte header */
122
123 /* Save rbx */
124 push rbx
125
126 /* Copy rcx to r8, as we need rcx for the exchange */
127 mov r8, rcx
128
129 ExpInterlockedPopEntrySListResume16:
130
131 /* Check if ListHead->NextEntry is NULL */
132 mov r9, rdx
133 and r9, SLIST16B_NEXTENTY_MASK
134 jz RtlInterlockedPopEntrySListEmpty16
135
136 ExpInterlockedPopEntrySListFault16:
137
138 /* Get next pointer */
139 mov rcx, [r9]
140
141 /* Set ListHead->HeaderType = 1 and ListHead->Init = 1 */
142 or rcx, 0x3
143
144 /* Copy Depth and Sequence number and adjust Depth */
145 lea rbx, [rax - SLIST16A_DEPTH_INC]
146
147 ExpInterlockedPopEntrySListEnd16:
148
149 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
150 lock cmpxchg16b [r8]
151
152 /* If not equal, retry with rdx:rax, being the content of [r8] now */
153 jnz ExpInterlockedPopEntrySListResume16
154
155 /* Copy the old NextEntry pointer to rax */
156 mov rax, rdx
157 and rax, SLIST16B_NEXTENTY_MASK
158
159 /* Return */
160 pop rbx
161 ret
162
163 RtlInterlockedPopEntrySListEmpty16:
164 xor rax, rax
165 pop rbx
166 ret
167
168 .endp RtlInterlockedPopEntrySList
169
170
171 /* PSLIST_ENTRY
172 * NTAPI
173 * RtlInterlockedPushEntrySList(
174 * IN PSLIST_HEADER ListHead,
175 * IN PSLIST_ENTRY ListEntry);
176 */
177 .proc RtlInterlockedPushEntrySList
178 ExpInterlockedPushEntrySList:
179
180 /* Load ListHead->Alignment into rax */
181 mov rax, [rcx]
182
183 /* Load ListHead->Region into rdx */
184 mov r9, [rcx + 8]
185
186 /* Check what kind of header this is */
187 test r9, SLIST8B_HEADERTYPE_MASK
188 jnz RtlInterlockedPushEntrySList16
189
190 /* We have an 8 byte header */
191
192 RtlInterlockedPushEntrySListLoop:
193
194 /* Get ListHead->NextEntry */
195 mov r8, rax
196 and r8, SLIST8A_NEXTENTRY_MASK
197 jz RtlInterlockedPushEntrySListEmpty
198
199 /* Shift the NextEntry pointer */
200 shr r8, SLIST8A_NEXTENTRY_SHIFT
201
202 /* Create a pointer template from rcx in rdx */
203 mov r9, ~SLIST8_POINTER_MASK
204 and r9, rcx
205
206 /* Combine to new pointer and save as ListEntry->NextEntry */
207 or r8, r9
208
209 RtlInterlockedPushEntrySListEmpty:
210 /* Store the NextEntry pointer in the new ListEntry */
211 mov [rdx], r8
212
213 /* Shift and mask the new ListEntry pointer */
214 mov r8, rdx
215 shl r8, SLIST8A_NEXTENTRY_SHIFT
216 and r8, SLIST8A_NEXTENTRY_MASK
217
218 /* Copy and adjust depth and sequence number */
219 lea r9, [rax + SLIST8A_DEPTH_INC + SLIST8A_SEQUENCE_INC]
220 and r9, SLIST8A_SEQUENCE_MASK | SLIST8A_DEPTH_MASK
221
222 /* Combine to exchange value in r8 */
223 or r8, r9
224
225 /* Save the NextEntry in r9 */
226 mov r9, [rdx]
227
228 /* If [rcx] equals rax, exchange it with r8 */
229 lock cmpxchg [rcx], r8
230
231 /* If not equal, retry with rax, being the content of [rcx] now */
232 jnz RtlInterlockedPushEntrySListLoop
233
234 /* Return the old NextEntry pointer */
235 mov rax, r9
236 ret
237
238 RtlInterlockedPushEntrySList16:
239 /* This is a 16 byte header */
240
241 /* Save rbx */
242 push rbx
243
244 /* Copy rcx/rdx to r8/r9, as we need rcx/rdx for the exchange */
245 mov r8, rcx
246 mov r9, rdx
247
248 /* Set ListHead->HeaderType = 1 and ListHead->Init = 1 */
249 mov rcx, rdx
250 or rcx, 0x3
251
252 mov rdx, [r8 + 8]
253
254 RtlInterlockedPushEntrySListLoop16:
255
256 /* Move ListHead->NextEntry to rbx */
257 mov rbx, rdx
258 and rbx, SLIST16B_NEXTENTY_MASK
259
260 /* Store next pointer in ListEntry->NextEntry */
261 mov [r9], rbx
262
263 /* Copy Depth and Sequence number and adjust Depth */
264 lea rbx, [rax + SLIST16A_DEPTH_INC + SLIST16A_SEQUENCE_INC]
265
266 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
267 lock cmpxchg16b [r8]
268
269 /* If not equal, retry with rdx:rax, being the content of [r8] now */
270 jnz RtlInterlockedPushEntrySListLoop16
271
272 /* Copy the old NextEntry pointer to rax */
273 mov rax, rdx
274 and rax, SLIST16B_NEXTENTY_MASK
275
276 /* Return */
277 pop rbx
278 ret
279
280 .endp RtlInterlockedPushEntrySList
281
282 /* PSLIST_ENTRY
283 * NTAPI
284 * RtlInterlockedFlushSList(
285 * IN PSINGLE_LIST_ENTRY ListHead);
286 */
287 .proc RtlInterlockedFlushSList
288 ExpInterlockedFlushSList:
289
290 /* Load ListHead->Region into rdx */
291 mov rax, [rcx + 8]
292
293 /* Check what kind of header this is */
294 test rax, SLIST8B_HEADERTYPE_MASK
295 jnz RtlInterlockedFlushSList16
296
297 /* We have an 8 byte header */
298
299 RtlInterlockedFlushSListLoop:
300
301 /* Zero ListHead->Alignment */
302 xor r8, r8
303
304 /* If [rcx] equals rax, exchange it with r8 */
305 lock cmpxchg [rcx], r8
306
307 /* If not equal, retry with rax, being the content of [rcx] now */
308 jnz RtlInterlockedFlushSListLoop
309
310 /* Use rcx as pointer template */
311 mov rdx, ~SLIST8_POINTER_MASK
312 or rdx, rcx
313
314 /* Combine result and return */
315 or rax, rdx
316 ret
317
318 RtlInterlockedFlushSList16:
319 /* We have a 16 byte header */
320 push rbx
321
322 mov rdx, [rcx + 8]
323 xor rbx, rbx
324 mov rcx, 0x3
325
326 RtlInterlockedFlushSListLoop16:
327
328 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
329 lock cmpxchg16b [r8]
330
331 /* If not equal, retry with rdx:rax, being the content of [r8] now */
332 jnz RtlInterlockedFlushSListLoop16
333
334 /* Copy the old NextEntry pointer to rax */
335 mov rax, rdx
336 and rax, SLIST16B_NEXTENTY_MASK
337
338 /* Return */
339 pop rbx
340 ret
341
342 .endp RtlInterlockedFlushSList