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 RtlInterlockedPopEntrySList 87PUBLIC RtlInterlockedPushEntrySList 88PUBLIC RtlInterlockedFlushSList 89 90/* PSLIST_ENTRY 91 * NTAPI 92 * RtlInterlockedPopEntrySList( 93 * IN PSLIST_HEADER ListHead); 94 */ 95ExpInterlockedPopEntrySList: 96FUNC RtlInterlockedPopEntrySList 97 .ENDPROLOG 98 99 /* Load ListHead->Region into rdx */ 100 mov rdx, [rcx + 8] 101 102 /* Load ListHead->Alignment into rax */ 103 mov rax, [rcx] 104 105 /* Check for 16 byte SList support */ 106 cmp byte ptr [rip+RtlpUse16ByteSLists], 0 107 jne RtlInterlockedPopEntrySList16 108 109 /* Use the 8 byte header */ 110GLOBAL_LABEL ExpInterlockedPopEntrySListResume 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 131GLOBAL_LABEL ExpInterlockedPopEntrySListFault 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 142GLOBAL_LABEL ExpInterlockedPopEntrySListEnd 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 164 xor rax, rax 165 ret 166 167ENDFUNC 168 169 170FUNC RtlInterlockedPopEntrySList16 171 mov [rsp + P3Home], rbx 172 .SAVEREG rbx, P3Home 173 .ENDPROLOG 174 175 /* This is a 16 byte header 176 rcx == ListHead 177 rdx == ListHead->Region 178 rax == ListHead->Alignment */ 179 180 /* Copy rcx to r8, as we need rcx for the exchange */ 181 mov r8, rcx 182 183GLOBAL_LABEL ExpInterlockedPopEntrySListResume16 184 185 /* Set r9 = ListHead->NextEntry and check if it is NULL */ 186 mov r9, rdx 187 and r9, SLIST16B_NEXTENTRY_MASK 188 jz RtlInterlockedPopEntrySListEmpty16 189 190GLOBAL_LABEL ExpInterlockedPopEntrySListFault16 191 192 /* Set NewListHead.Next = ListHead->NextEntry->Next */ 193 mov rcx, [r9] 194 195 /* Set NewListHead.HeaderType = 1 and NewListHead.Init = 1 */ 196 or rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK) 197 198 /* Copy Depth and Sequence number and adjust Depth */ 199 lea rbx, [rax - SLIST16A_DEPTH_INC] 200 201GLOBAL_LABEL ExpInterlockedPopEntrySListEnd16 202 203 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ 204 lock cmpxchg16b [r8] 205 206 /* If not equal, retry with rdx:rax, being the content of [r8] now */ 207 jne ExpInterlockedPopEntrySListResume16 208 209 /* Copy the old NextEntry pointer to rax */ 210 mov rax, rdx 211 and rax, SLIST16B_NEXTENTRY_MASK 212 213 /* Return */ 214 mov rbx, [rsp + P3Home] 215 ret 216 217RtlInterlockedPopEntrySListEmpty16: 218 219 xor rax, rax 220 mov rbx, [rsp + P3Home] 221 ret 222ENDFUNC 223 224 225/* PSLIST_ENTRY 226 * NTAPI 227 * RtlInterlockedPushEntrySList( 228 * IN PSLIST_HEADER ListHead, 229 * IN PSLIST_ENTRY ListEntry); 230 */ 231ExpInterlockedPushEntrySList: 232FUNC RtlInterlockedPushEntrySList 233 .ENDPROLOG 234 235#if DBG 236 /* Make sure the ListEntry is 16 bytes aligned */ 237 test rdx, HEX(0F) 238 jz ExpInterlockedPushEntrySListChecked 239 /* Not aligned, raise an assertion */ 240 int HEX(2C) 241ExpInterlockedPushEntrySListChecked: 242 243 /* Make sure RtlpUse16ByteSLists is initialized */ 244 cmp byte ptr [rip+RtlpUse16ByteSLists], HEX(FF) 245 jne ExpInterlockedPushEntrySListChecked2 246 /* Not initialized, raise an assertion */ 247 int HEX(2C) 248ExpInterlockedPushEntrySListChecked2: 249#endif 250 251 /* Load ListHead->Alignment into rax */ 252 mov rax, [rcx] 253 254 /* Load ListHead->Region into r9 */ 255 mov r9, [rcx + 8] 256 257 /* Check for 16 byte SList support */ 258 cmp byte ptr [rip+RtlpUse16ByteSLists], 0 259 jne RtlInterlockedPushEntrySList16 260 261 /* Use the 8 byte header */ 262 263RtlInterlockedPushEntrySListLoop: 264 265 /* Get ListHead->NextEntry */ 266 mov r8, rax 267 and r8, SLIST8A_NEXTENTRY_MASK 268 jz RtlInterlockedPushEntrySListEmpty 269 270 /* Shift the NextEntry pointer */ 271 shr r8, SLIST8A_NEXTENTRY_SHIFT 272 273 /* Create a pointer template from rcx in rdx */ 274 mov r9, (NOT SLIST8_POINTER_MASK) 275 and r9, rcx 276 277 /* Combine to new pointer and save as ListEntry->NextEntry */ 278 or r8, r9 279 280RtlInterlockedPushEntrySListEmpty: 281 /* Store the NextEntry pointer in the new ListEntry */ 282 mov [rdx], r8 283 284 /* Shift and mask the new ListEntry pointer */ 285 mov r8, rdx 286 shl r8, SLIST8A_NEXTENTRY_SHIFT 287 and r8, SLIST8A_NEXTENTRY_MASK 288 289 /* Copy and adjust depth and sequence number */ 290 lea r9, [rax + SLIST8A_DEPTH_INC + SLIST8A_SEQUENCE_INC] 291 and r9, SLIST8A_SEQUENCE_MASK OR SLIST8A_DEPTH_MASK 292 293 /* Combine to exchange value in r8 */ 294 or r8, r9 295 296 /* Save the NextEntry in r9 */ 297 mov r9, [rdx] 298 299 /* If [rcx] equals rax, exchange it with r8 */ 300 lock cmpxchg [rcx], r8 301 302 /* If not equal, retry with rax, being the content of [rcx] now */ 303 jne RtlInterlockedPushEntrySListLoop 304 305 /* Return the old NextEntry pointer */ 306 mov rax, r9 307 ret 308 309ENDFUNC 310 311FUNC RtlInterlockedPushEntrySList16 312 mov [rsp + P3Home], rbx 313 .SAVEREG rbx, P3Home 314 .ENDPROLOG 315 316 /* This is a 16 byte header 317 rcx = ListHead 318 rdx = ListEntry 319 rax = ListHead->Alignment 320 r9 = ListHead->Region */ 321 322 /* Copy rcx/rdx to r8/r9, as we need rcx/rdx for the exchange */ 323 mov r8, rcx 324 mov r9, rdx 325 326 /* Set NewListHead.NextEntry = ListEntry */ 327 mov rcx, rdx 328 329 /* Set NewListHead.HeaderType = 1 and NewListHead.Init = 1 */ 330 or rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK) 331 332 /* Set rdx = ListHead->Region */ 333 mov rdx, [r8 + 8] 334 335RtlInterlockedPushEntrySListLoop16: 336 /* r8 = ListHead 337 r9 = ListEntry 338 rax = ListHead->Alignment 339 rdx = ListHead->Region 340 */ 341 342 /* Move ListHead->NextEntry to rbx */ 343 mov rbx, rdx 344 and rbx, SLIST16B_NEXTENTRY_MASK 345 346 /* Store next pointer in ListEntry->Next */ 347 mov [r9], rbx 348 349 /* Copy and increment Depth and Sequence number to rbx */ 350 lea rbx, [rax + SLIST16A_DEPTH_INC + SLIST16A_SEQUENCE_INC] 351 352 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ 353 lock cmpxchg16b [r8] 354 355 /* If not equal, retry with rdx:rax, being the content of [r8] now */ 356 jne RtlInterlockedPushEntrySListLoop16 357 358 /* Copy the old NextEntry pointer to rax */ 359 mov rax, rdx 360 and rax, SLIST16B_NEXTENTRY_MASK 361 362 /* Return */ 363 mov rbx, [rsp + P3Home] 364 ret 365 366ENDFUNC 367 368 369/* PSLIST_ENTRY 370 * NTAPI 371 * RtlInterlockedFlushSList( 372 * IN PSLIST_HEADER ListHead); 373 */ 374ExpInterlockedFlushSList: 375FUNC RtlInterlockedFlushSList 376 377 mov [rsp + P3Home], rbx 378 .SAVEREG rbx, P3Home 379 .ENDPROLOG 380 381 /* Load ListHead->Region into rdx */ 382 mov rdx, [rcx + 8] 383 384 /* Load ListHead->Alignment into rax */ 385 mov rax, [rcx] 386 387 /* Check for 16 byte SList support */ 388 cmp byte ptr [rip+RtlpUse16ByteSLists], 0 389 jne RtlInterlockedFlushSList16 390 391 /* Use the 8 byte header */ 392 393RtlInterlockedFlushSListLoop: 394 395 /* Zero NewListHead.Alignment */ 396 xor r8, r8 397 398 /* If [rcx] equals rax, exchange it with r8 */ 399 lock cmpxchg [rcx], r8 400 401 /* If not equal, retry with rax, being the content of [rcx] now */ 402 jne RtlInterlockedFlushSListLoop 403 404 /* Create a pointer template from rcx in rdx */ 405 mov rdx, (NOT SLIST8_POINTER_MASK) 406 and rdx, rcx 407 408 /* Load the old NextEntry pointer into rax */ 409 and rax, SLIST8A_NEXTENTRY_MASK 410 shr rax, SLIST8A_NEXTENTRY_SHIFT 411 412 /* Combine result and return */ 413 or rax, rdx 414 ret 415 416RtlInterlockedFlushSList16: 417 /* We have a 16 byte header 418 rcx = ListHead 419 rax = ListHead->Alignment 420 rdx = ListHead->Region 421 */ 422 423 /* Load ListHead into r8, as we need rcx for the exchange */ 424 mov r8, rcx 425 426 /* Initialize an ampty NewListHead in rcx:rbx */ 427 xor rbx, rbx 428 mov rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK) 429 430RtlInterlockedFlushSListLoop16: 431 432 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ 433 lock cmpxchg16b [r8] 434 435 /* If not equal, retry with rdx:rax, being the content of [r8] now */ 436 jne RtlInterlockedFlushSListLoop16 437 438 /* Copy the old NextEntry pointer to rax */ 439 mov rax, rdx 440 and rax, SLIST16B_NEXTENTRY_MASK 441 442 /* Return */ 443 mov rbx, [rsp + P3Home] 444 ret 445 446ENDFUNC 447 448END 449 450