1/* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: lib/rtl/amd64/slist.S 5 * PURPOSE: Rtl Interlocked Functions for amd64 6 * PROGRAMMERS: Timo Kreuzer 7 */ 8 9#include <asm.inc> 10#include <ksamd64.inc> 11 12EXTERN RtlpUse16ByteSLists:BYTE 13 14/* 15typedef union DECLSPEC_ALIGN(16) _SLIST_HEADER 16{ 17 struct 18 { 19 ULONGLONG Alignment; 20 ULONGLONG Region; 21 }; 22 struct 23 { 24 ULONGLONG Depth:16; 25 ULONGLONG Sequence:9; 26 ULONGLONG NextEntry:39; 27 ULONGLONG HeaderType:1; 28 ULONGLONG Init:1; 29 ULONGLONG Reserved:59; 30 ULONGLONG Region:3; 31 } Header8; 32 struct 33 { 34 ULONGLONG Depth:16; 35 ULONGLONG Sequence:48; 36 ULONGLONG HeaderType:1; 37 ULONGLONG Init:1; 38 ULONGLONG Reserved:2; 39 ULONGLONG NextEntry:60; 40 } Header16; 41 struct 42 { 43 ULONGLONG Depth:16; 44 ULONGLONG Sequence:48; 45 ULONGLONG HeaderType:1; 46 ULONGLONG Reserved:3; 47 ULONGLONG NextEntry:60; 48 } HeaderX64; 49} SLIST_HEADER, *PSLIST_HEADER; 50*/ 51 52#define SLIST8A_DEPTH_MASK HEX(000000000000FFFF) 53#define SLIST8A_DEPTH_INC HEX(0000000000000001) 54#define SLIST8A_SEQUENCE_MASK HEX(0000000001FF0000) 55#define SLIST8A_SEQUENCE_INC HEX(0000000000010000) 56#define SLIST8A_NEXTENTRY_MASK HEX(FFFFFFFFFE000000) 57#define SLIST8A_NEXTENTRY_SHIFT 21 58#define SLIST8B_HEADERTYPE_MASK HEX(0000000000000001) 59#define SLIST8B_INIT_MASK HEX(0000000000000002) 60#define SLIST8B_REGION_MASK HEX(E000000000000000) 61#define SLIST8_POINTER_MASK HEX(000007FFFFFFFFFF) 62 63#define SLIST16A_DEPTH_MASK HEX(000000000000FFFF) 64#define SLIST16A_DEPTH_INC HEX(0000000000000001) 65#define SLIST16A_SEQUENCE_MASK HEX(FFFFFFFFFFFF0000) 66#define SLIST16A_SEQUENCE_INC HEX(0000000000010000) 67#define SLIST16B_HEADERTYPE_MASK HEX(0000000000000001) 68#define SLIST16B_INIT_MASK HEX(0000000000000002) 69#define SLIST16B_NEXTENTRY_MASK HEX(FFFFFFFFFFFFFFF0) 70 71 72/* FUNCTIONS ****************************************************************/ 73 74.code64 75 76PUBLIC ExpInterlockedPopEntrySList 77PUBLIC ExpInterlockedPopEntrySListResume 78PUBLIC ExpInterlockedPopEntrySListFault 79PUBLIC ExpInterlockedPopEntrySListEnd 80PUBLIC ExpInterlockedPopEntrySListResume16 81PUBLIC ExpInterlockedPopEntrySListFault16 82PUBLIC ExpInterlockedPopEntrySListEnd16 83PUBLIC ExpInterlockedPushEntrySList 84PUBLIC ExpInterlockedFlushSList 85 86PUBLIC RtlInterlockedFlushSList 87PUBLIC RtlInterlockedPopEntrySList 88PUBLIC RtlInterlockedPushEntrySList 89 90/* PSLIST_ENTRY 91 * NTAPI 92 * RtlInterlockedPopEntrySList( 93 * IN PSLIST_HEADER ListHead); 94 */ 95RtlInterlockedPopEntrySList: 96ExpInterlockedPopEntrySList: 97 98 /* Load ListHead->Region into rdx */ 99 mov rdx, [rcx + 8] 100 101 /* Load ListHead->Alignment into rax */ 102 mov rax, [rcx] 103 104 /* Check for 16 byte SList support */ 105 cmp byte ptr [RtlpUse16ByteSLists], 0 106 jne RtlInterlockedPopEntrySList16 107 108 /* Use the 8 byte header */ 109 110ExpInterlockedPopEntrySListResume: 111 112 /* Check if ListHead->NextEntry is NULL */ 113 mov r9, rax 114 and r9, SLIST8A_NEXTENTRY_MASK 115 jz RtlInterlockedPopEntrySListEmpty 116 117 /* Copy Depth and Sequence number and adjust Depth */ 118 lea r8, [rax - SLIST8A_DEPTH_INC] 119 and r8, (SLIST8A_SEQUENCE_MASK OR SLIST8A_DEPTH_MASK) 120 121 /* Create a pointer template from rcx in rdx */ 122 mov rdx, (NOT SLIST8_POINTER_MASK) 123 and rdx, rcx 124 125 /* Shift the NextEntry pointer */ 126 shr r9, SLIST8A_NEXTENTRY_SHIFT 127 128 /* Combine to new pointer in rdx */ 129 or rdx, r9 130 131ExpInterlockedPopEntrySListFault: 132 133 /* Load the next NextEntry pointer to r9 */ 134 mov r9, [rdx] 135 136 /* Shift bits in place */ 137 shl r9, SLIST8A_NEXTENTRY_SHIFT 138 139 /* Combine into r8 */ 140 or r8, r9 141 142ExpInterlockedPopEntrySListEnd: 143 144 /* If [rcx] equals rax, exchange it with r8 */ 145 lock cmpxchg [rcx], r8 146 147 /* If not equal, retry with rax, being the content of [rcx] now */ 148 jne ExpInterlockedPopEntrySListResume 149 150 /* Shift the pointer bits in place */ 151 and rax, SLIST8A_NEXTENTRY_MASK 152 shr rax, SLIST8A_NEXTENTRY_SHIFT 153 154 /* Use rcx as pointer template */ 155 mov rdx, (NOT SLIST8_POINTER_MASK) 156 and rdx, rcx 157 158 /* Combine result and return */ 159 or rax, rdx 160 ret 161 162RtlInterlockedPopEntrySListEmpty: 163 xor rax, rax 164 ret 165 166RtlInterlockedPopEntrySList16: 167 /* This is a 16 byte header 168 rcx == ListHead 169 rdx == ListHead->Region 170 rax == ListHead->Alignment */ 171 172 /* Save rbx */ 173 push rbx 174 175 /* Copy rcx to r8, as we need rcx for the exchange */ 176 mov r8, rcx 177 178ExpInterlockedPopEntrySListResume16: 179 180 /* Set r9 = ListHead->NextEntry and check if it is NULL */ 181 mov r9, rdx 182 and r9, SLIST16B_NEXTENTRY_MASK 183 jz RtlInterlockedPopEntrySListEmpty16 184 185ExpInterlockedPopEntrySListFault16: 186 187 /* Set NewListHead.Next = ListHead->NextEntry->Next */ 188 mov rcx, [r9] 189 190 /* Set NewListHead.HeaderType = 1 and NewListHead.Init = 1 */ 191 or rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK) 192 193 /* Copy Depth and Sequence number and adjust Depth */ 194 lea rbx, [rax - SLIST16A_DEPTH_INC] 195 196ExpInterlockedPopEntrySListEnd16: 197 198 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ 199 lock cmpxchg16b [r8] 200 201 /* If not equal, retry with rdx:rax, being the content of [r8] now */ 202 jne ExpInterlockedPopEntrySListResume16 203 204 /* Copy the old NextEntry pointer to rax */ 205 mov rax, rdx 206 and rax, SLIST16B_NEXTENTRY_MASK 207 208 /* Return */ 209 pop rbx 210 ret 211 212RtlInterlockedPopEntrySListEmpty16: 213 xor rax, rax 214 pop rbx 215 ret 216 217 218/* PSLIST_ENTRY 219 * NTAPI 220 * RtlInterlockedPushEntrySList( 221 * IN PSLIST_HEADER ListHead, 222 * IN PSLIST_ENTRY ListEntry); 223 */ 224RtlInterlockedPushEntrySList: 225ExpInterlockedPushEntrySList: 226 227#if DBG 228 /* Make sure the ListEntry is 16 bytes aligned */ 229 test rdx, HEX(0F) 230 jz ExpInterlockedPushEntrySListChecked 231 /* Not aligned, raise an assertion */ 232 int HEX(2C) 233ExpInterlockedPushEntrySListChecked: 234 235 /* Make sure RtlpUse16ByteSLists is initialized */ 236 cmp byte ptr [RtlpUse16ByteSLists], HEX(FF) 237 jne ExpInterlockedPushEntrySListChecked2 238 /* Not initialized, raise an assertion */ 239 int HEX(2C) 240ExpInterlockedPushEntrySListChecked2: 241#endif 242 243 /* Load ListHead->Alignment into rax */ 244 mov rax, [rcx] 245 246 /* Load ListHead->Region into r9 */ 247 mov r9, [rcx + 8] 248 249 /* Check for 16 byte SList support */ 250 cmp byte ptr [RtlpUse16ByteSLists], 0 251 jne RtlInterlockedPushEntrySList16 252 253 /* Use the 8 byte header */ 254 255RtlInterlockedPushEntrySListLoop: 256 257 /* Get ListHead->NextEntry */ 258 mov r8, rax 259 and r8, SLIST8A_NEXTENTRY_MASK 260 jz RtlInterlockedPushEntrySListEmpty 261 262 /* Shift the NextEntry pointer */ 263 shr r8, SLIST8A_NEXTENTRY_SHIFT 264 265 /* Create a pointer template from rcx in rdx */ 266 mov r9, (NOT SLIST8_POINTER_MASK) 267 and r9, rcx 268 269 /* Combine to new pointer and save as ListEntry->NextEntry */ 270 or r8, r9 271 272RtlInterlockedPushEntrySListEmpty: 273 /* Store the NextEntry pointer in the new ListEntry */ 274 mov [rdx], r8 275 276 /* Shift and mask the new ListEntry pointer */ 277 mov r8, rdx 278 shl r8, SLIST8A_NEXTENTRY_SHIFT 279 and r8, SLIST8A_NEXTENTRY_MASK 280 281 /* Copy and adjust depth and sequence number */ 282 lea r9, [rax + SLIST8A_DEPTH_INC + SLIST8A_SEQUENCE_INC] 283 and r9, SLIST8A_SEQUENCE_MASK OR SLIST8A_DEPTH_MASK 284 285 /* Combine to exchange value in r8 */ 286 or r8, r9 287 288 /* Save the NextEntry in r9 */ 289 mov r9, [rdx] 290 291 /* If [rcx] equals rax, exchange it with r8 */ 292 lock cmpxchg [rcx], r8 293 294 /* If not equal, retry with rax, being the content of [rcx] now */ 295 jne RtlInterlockedPushEntrySListLoop 296 297 /* Return the old NextEntry pointer */ 298 mov rax, r9 299 ret 300 301RtlInterlockedPushEntrySList16: 302 /* This is a 16 byte header 303 rcx = ListHead 304 rdx = ListEntry 305 rax = ListHead->Alignment 306 r9 = ListHead->Region */ 307 308 /* Save rbx */ 309 push rbx 310 311 /* Copy rcx/rdx to r8/r9, as we need rcx/rdx for the exchange */ 312 mov r8, rcx 313 mov r9, rdx 314 315 /* Set NewListHead.NextEntry = ListEntry */ 316 mov rcx, rdx 317 318 /* Set NewListHead.HeaderType = 1 and NewListHead.Init = 1 */ 319 or rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK) 320 321 /* Set rdx = ListHead->Region */ 322 mov rdx, [r8 + 8] 323 324RtlInterlockedPushEntrySListLoop16: 325 /* r8 = ListHead 326 r9 = ListEntry 327 rax = ListHead->Alignment 328 rdx = ListHead->Region 329 */ 330 331 /* Move ListHead->NextEntry to rbx */ 332 mov rbx, rdx 333 and rbx, SLIST16B_NEXTENTRY_MASK 334 335 /* Store next pointer in ListEntry->Next */ 336 mov [r9], rbx 337 338 /* Copy and increment Depth and Sequence number to rbx */ 339 lea rbx, [rax + SLIST16A_DEPTH_INC + SLIST16A_SEQUENCE_INC] 340 341 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ 342 lock cmpxchg16b [r8] 343 344 /* If not equal, retry with rdx:rax, being the content of [r8] now */ 345 jne RtlInterlockedPushEntrySListLoop16 346 347 /* Copy the old NextEntry pointer to rax */ 348 mov rax, rdx 349 and rax, SLIST16B_NEXTENTRY_MASK 350 351 /* Return */ 352 pop rbx 353 ret 354 355 356/* PSLIST_ENTRY 357 * NTAPI 358 * RtlInterlockedFlushSList( 359 * IN PSLIST_HEADER ListHead); 360 */ 361RtlInterlockedFlushSList: 362ExpInterlockedFlushSList: 363 364 /* Load ListHead->Region into rdx */ 365 mov rdx, [rcx + 8] 366 367 /* Load ListHead->Alignment into rax */ 368 mov rax, [rcx] 369 370 /* Check for 16 byte SList support */ 371 cmp byte ptr [RtlpUse16ByteSLists], 0 372 jne RtlInterlockedFlushSList16 373 374 /* Use the 8 byte header */ 375 376RtlInterlockedFlushSListLoop: 377 378 /* Zero NewListHead.Alignment */ 379 xor r8, r8 380 381 /* If [rcx] equals rax, exchange it with r8 */ 382 lock cmpxchg [rcx], r8 383 384 /* If not equal, retry with rax, being the content of [rcx] now */ 385 jne RtlInterlockedFlushSListLoop 386 387 /* Create a pointer template from rcx in rdx */ 388 mov rdx, (NOT SLIST8_POINTER_MASK) 389 and rdx, rcx 390 391 /* Load the old NextEntry pointer into rax */ 392 and rax, SLIST8A_NEXTENTRY_MASK 393 shr rax, SLIST8A_NEXTENTRY_SHIFT 394 395 /* Combine result and return */ 396 or rax, rdx 397 ret 398 399RtlInterlockedFlushSList16: 400 /* We have a 16 byte header 401 rcx = ListHead 402 rax = ListHead->Alignment 403 rdx = ListHead->Region 404 */ 405 406 /* Save rbx */ 407 push rbx 408 409 /* Load ListHead into r8, as we need rcx for the exchange */ 410 mov r8, rcx 411 412 /* Initialize an ampty NewListHead in rcx:rbx */ 413 xor rbx, rbx 414 mov rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK) 415 416RtlInterlockedFlushSListLoop16: 417 418 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ 419 lock cmpxchg16b [r8] 420 421 /* If not equal, retry with rdx:rax, being the content of [r8] now */ 422 jne RtlInterlockedFlushSListLoop16 423 424 /* Copy the old NextEntry pointer to rax */ 425 mov rax, rdx 426 and rax, SLIST16B_NEXTENTRY_MASK 427 428 /* Return */ 429 pop rbx 430 ret 431 432END 433 434