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