v2 / vlib / x / atomics / atomics.amd64.v
772 lines · 744 sloc · 13.97 KB · 1c4bb916e5cdf6aecbc6c6315f95453a9e8778f3
Raw
1module atomics
2
3// add_i32 atomically adds delta to the value at dest and returns the new value.
4// The operation is performed with sequential consistency.
5// Panics if dest is not 4-byte aligned.
6pub fn add_i32(dest &i32, delta i32) i32 {
7 mut result := i32(0)
8 asm volatile amd64 {
9 mov rdx, dest
10 test rdx, 3
11 jz '1f'
12 call panicUnaligned
13 jmp '2f'
14 1:
15 mov eax, delta
16 lock xadd [rdx], eax
17 add eax, delta
18 mov result, eax
19 2:
20 ; =r (result)
21 ; r (dest)
22 r (delta)
23 ; eax
24 rdx
25 memory
26 }
27 return result
28}
29
30// swap_i32 atomically stores new value at dest and returns the old value.
31// The operation is performed with sequential consistency.
32// Panics if dest is not 4-byte aligned.
33pub fn swap_i32(dest &i32, new i32) i32 {
34 mut old := i32(0)
35 asm volatile amd64 {
36 mov rdx, dest
37 test rdx, 3
38 jz '1f'
39 call panicUnaligned
40 jmp '2f'
41 1:
42 mov eax, new
43 xchg [rdx], eax
44 mov old, eax
45 2:
46 ; =r (old)
47 ; r (dest)
48 r (new)
49 ; eax
50 rdx
51 memory
52 }
53 return old
54}
55
56// store_i32 atomically stores value at dest.
57// The operation is performed with sequential consistency.
58// Panics if dest is not 4-byte aligned.
59pub fn store_i32(dest &i32, value i32) {
60 asm volatile amd64 {
61 mov rdx, dest
62 test rdx, 3
63 jz '1f'
64 call panicUnaligned
65 jmp '2f'
66 1:
67 mov eax, value
68 xchg eax, [rdx]
69 2:
70 ; ; r (dest)
71 r (value)
72 ; eax
73 rdx
74 memory
75 }
76}
77
78// load_i32 atomically loads and returns the value at num.
79// The operation is performed with sequential consistency.
80// Panics if num is not 4-byte aligned.
81pub fn load_i32(num &i32) i32 {
82 mut out := i32(0)
83 asm volatile amd64 {
84 mov rdx, num
85 test rdx, 3
86 jz '1f'
87 call panicUnaligned
88 jmp '2f'
89 1:
90 mov eax, [rdx]
91 mov out, eax
92 2:
93 ; =r (out)
94 ; r (num)
95 ; eax
96 rdx
97 memory
98 }
99 return out
100}
101
102// cas_i32 performs a compare-and-swap operation.
103// If the current value at addr equals old, it atomically stores new.
104// Returns true if the swap was performed, false otherwise.
105// The operation is performed with sequential consistency.
106// Panics if addr is not 4-byte aligned.
107pub fn cas_i32(addr &i32, old i32, new i32) bool {
108 mut swapped := false
109 asm volatile amd64 {
110 mov rdx, addr
111 test rdx, 3
112 jz '1f'
113 call panicUnaligned
114 jmp '2f'
115 1:
116 mov eax, old
117 mov ecx, new
118 lock cmpxchg [rdx], ecx
119 sete al
120 mov swapped, al
121 2:
122 ; =r (swapped)
123 ; r (addr)
124 r (old)
125 r (new)
126 ; eax
127 ecx
128 rdx
129 memory
130 }
131 return swapped
132}
133
134// store_i64 atomically stores value at dest.
135// The operation is performed with sequential consistency.
136// Panics if dest is not 8-byte aligned.
137pub fn store_i64(dest &i64, value i64) {
138 asm volatile amd64 {
139 mov rdx, dest
140 test rdx, 7
141 jz '1f'
142 call panicUnaligned
143 jmp '2f'
144 1:
145 mov rax, value
146 xchg rax, [rdx]
147 2:
148 ; ; r (dest)
149 r (value)
150 ; rax
151 rdx
152 memory
153 }
154}
155
156// load_i64 atomically loads and returns the value at num.
157// The operation is performed with sequential consistency.
158// Panics if num is not 8-byte aligned.
159pub fn load_i64(num &i64) i64 {
160 mut out := i64(0)
161 asm volatile amd64 {
162 mov rdx, num
163 test rdx, 7
164 jz '1f'
165 call panicUnaligned
166 jmp '2f'
167 1:
168 mov rax, [rdx]
169 mov out, rax
170 2:
171 ; =r (out)
172 ; r (num)
173 ; rax
174 rdx
175 memory
176 }
177 return out
178}
179
180// add_i64 atomically adds delta to the value at dest and returns the new value.
181// The operation is performed with sequential consistency.
182// Panics if dest is not 8-byte aligned.
183pub fn add_i64(dest &i64, delta i64) i64 {
184 mut result := i64(0)
185 asm volatile amd64 {
186 mov rdx, dest
187 test rdx, 7
188 jz '1f'
189 call panicUnaligned
190 jmp '2f'
191 1:
192 mov rax, delta
193 lock xadd [rdx], rax
194 add rax, delta
195 mov result, rax
196 2:
197 ; =r (result)
198 ; r (delta)
199 r (dest)
200 ; rax
201 rdx
202 memory
203 }
204 return result
205}
206
207// swap_i64 atomically stores value at dest and returns the old value.
208// The operation is performed with sequential consistency.
209// Panics if dest is not 8-byte aligned.
210pub fn swap_i64(dest &i64, value i64) i64 {
211 mut old := i64(0)
212 asm volatile amd64 {
213 mov rdx, dest
214 test rdx, 7
215 jz '1f'
216 call panicUnaligned
217 jmp '2f'
218 1:
219 mov rax, value
220 xchg rax, [rdx]
221 mov old, rax
222 2:
223 ; =r (old)
224 ; r (dest)
225 r (value)
226 ; rax
227 rdx
228 memory
229 }
230 return old
231}
232
233// cas_i64 performs a compare-and-swap operation.
234// If the current value at addr equals old, it atomically stores new.
235// Returns true if the swap was performed, false otherwise.
236// The operation is performed with sequential consistency.
237// Panics if addr is not 8-byte aligned.
238pub fn cas_i64(addr &i64, old i64, new i64) bool {
239 mut swapped := false
240 asm volatile amd64 {
241 mov rdx, addr
242 test rdx, 7
243 jz '1f'
244 call panicUnaligned
245 jmp '2f'
246 1:
247 mov rax, old
248 mov rcx, new
249 lock cmpxchgq [rdx], rcx
250 sete al
251 mov swapped, al
252 2:
253 ; =r (swapped)
254 ; r (addr)
255 r (old)
256 r (new)
257 ; rax
258 rcx
259 rdx
260 memory
261 }
262 return swapped
263}
264
265// add_u32 atomically adds delta to the value at dest and returns the new value.
266// The operation is performed with sequential consistency.
267// Panics if dest is not 4-byte aligned.
268pub fn add_u32(dest &u32, delta u32) u32 {
269 mut result := u32(0)
270 asm volatile amd64 {
271 mov rdx, dest
272 test rdx, 3
273 jz '1f'
274 call panicUnaligned
275 jmp '2f'
276 1:
277 mov eax, delta
278 lock xadd [rdx], eax
279 add eax, delta
280 mov result, eax
281 2:
282 ; =r (result)
283 ; r (dest)
284 r (delta)
285 ; rax
286 rdx
287 memory
288 }
289 return result
290}
291
292// swap_u32 atomically stores new value at dest and returns the old value.
293// The operation is performed with sequential consistency.
294// Panics if dest is not 4-byte aligned.
295pub fn swap_u32(dest &u32, new u32) u32 {
296 mut old := u32(0)
297 asm volatile amd64 {
298 mov rdx, dest
299 test rdx, 3
300 jz '1f'
301 call panicUnaligned
302 jmp '2f'
303 1:
304 mov eax, new
305 xchg [rdx], eax
306 mov old, eax
307 2:
308 ; =r (old)
309 ; r (dest)
310 r (new)
311 ; eax
312 rdx
313 memory
314 }
315 return old
316}
317
318// store_u32 atomically stores value at dest.
319// The operation is performed with sequential consistency.
320// Panics if dest is not 4-byte aligned.
321pub fn store_u32(dest &u32, value u32) {
322 asm volatile amd64 {
323 mov rdx, dest
324 test rdx, 3
325 jz '1f'
326 call panicUnaligned
327 jmp '2f'
328 1:
329 mov eax, value
330 xchg eax, [rdx]
331 2:
332 ; ; r (dest)
333 r (value)
334 ; eax
335 rdx
336 memory
337 }
338}
339
340// load_u32 atomically loads and returns the value at num.
341// The operation is performed with sequential consistency.
342// Panics if num is not 4-byte aligned.
343pub fn load_u32(num &u32) u32 {
344 mut out := u32(0)
345 asm volatile amd64 {
346 mov rdx, num
347 test rdx, 3
348 jz '1f'
349 call panicUnaligned
350 jmp '2f'
351 1:
352 mov eax, [rdx]
353 mov out, eax
354 2:
355 ; =r (out)
356 ; r (num)
357 ; rax
358 rdx
359 }
360 return out
361}
362
363// cas_u32 performs a compare-and-swap operation.
364// If the current value at addr equals old, it atomically stores new.
365// Returns true if the swap was performed, false otherwise.
366// The operation is performed with sequential consistency.
367// Panics if addr is not 4-byte aligned.
368pub fn cas_u32(addr &u32, old u32, new u32) bool {
369 mut swapped := false
370 asm volatile amd64 {
371 mov rdx, addr
372 test rdx, 3
373 jz '1f'
374 call panicUnaligned
375 jmp '2f'
376 1:
377 mov eax, old
378 mov ecx, new
379 lock cmpxchg [rdx], ecx
380 sete al
381 mov swapped, al
382 2:
383 ; =r (swapped)
384 ; r (addr)
385 r (old)
386 r (new)
387 ; eax
388 ecx
389 rdx
390 memory
391 }
392 return swapped
393}
394
395// load_u64 atomically loads and returns the value at num.
396// The operation is performed with sequential consistency.
397// Panics if num is not 8-byte aligned.
398pub fn load_u64(num &u64) u64 {
399 mut out := u64(0)
400 asm volatile amd64 {
401 mov rdx, num
402 test rdx, 7
403 jz '1f'
404 call panicUnaligned
405 jmp '2f'
406 1:
407 mov rax, [rdx]
408 mov out, rax
409 2:
410 ; =r (out)
411 ; r (num)
412 ; rax
413 rdx
414 memory
415 }
416 return out
417}
418
419// store_u64 atomically stores value at dest.
420// The operation is performed with sequential consistency.
421// Panics if dest is not 8-byte aligned.
422pub fn store_u64(dest &u64, value u64) {
423 asm volatile amd64 {
424 mov rdx, dest
425 test rdx, 7
426 jz '1f'
427 call panicUnaligned
428 jmp '2f'
429 1:
430 mov rax, value
431 xchg rax, [rdx]
432 2:
433 ; ; r (dest)
434 r (value)
435 ; rax
436 rdx
437 memory
438 }
439}
440
441// add_u64 atomically adds delta to the value at dest and returns the new value.
442// The operation is performed with sequential consistency.
443// Panics if dest is not 8-byte aligned.
444pub fn add_u64(dest &u64, delta u64) u64 {
445 mut result := u64(0)
446 asm volatile amd64 {
447 mov rdx, dest
448 test rdx, 7
449 jz '1f'
450 call panicUnaligned
451 jmp '2f'
452 1:
453 mov rax, delta
454 lock xadd [rdx], rax
455 add rax, delta
456 mov result, rax
457 2:
458 ; =r (result)
459 ; r (dest)
460 r (delta)
461 ; rax
462 rdx
463 memory
464 }
465 return result
466}
467
468// swap_u64 atomically stores value at dest and returns the old value.
469// The operation is performed with sequential consistency.
470// Panics if dest is not 8-byte aligned.
471pub fn swap_u64(dest &u64, value u64) u64 {
472 mut old := u64(0)
473 asm volatile amd64 {
474 mov rdx, dest
475 test rdx, 7
476 jz '1f'
477 call panicUnaligned
478 jmp '2f'
479 1:
480 mov rax, value
481 xchg [rdx], rax
482 mov old, rax
483 2:
484 ; =r (old)
485 ; r (dest)
486 r (value)
487 ; rax
488 rdx
489 memory
490 }
491 return old
492}
493
494// cas_u64 performs a compare-and-swap operation.
495// If the current value at addr equals old, it atomically stores new.
496// Returns true if the swap was performed, false otherwise.
497// The operation is performed with sequential consistency.
498// Panics if addr is not 8-byte aligned.
499pub fn cas_u64(addr &u64, old u64, new u64) bool {
500 mut swapped := false
501 asm volatile amd64 {
502 mov rdx, addr
503 test rdx, 7
504 jz '1f'
505 call panicUnaligned
506 jmp '2f'
507 1:
508 mov rax, old
509 mov rcx, new
510 lock cmpxchgq [rdx], rcx
511 sete al
512 mov swapped, al
513 2:
514 ; =r (swapped)
515 ; r (addr)
516 r (old)
517 r (new)
518 ; rax
519 rcx
520 rdx
521 memory
522 }
523 return swapped
524}
525
526// and_i64 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
527// The operation is performed with sequential consistency.
528// Panics if addr is not 8-byte aligned.
529pub fn and_i64(addr &i64, mask i64) i64 {
530 mut old := i64(0)
531 asm volatile amd64 {
532 mov rdx, addr
533 test rdx, 7
534 jz '1f'
535 call panicUnaligned
536 jmp '2f'
537 1:
538 3:
539 mov rax, [rdx]
540 mov rcx, rax
541 and rcx, mask
542 lock cmpxchg [rdx], rcx
543 jnz '3b'
544 mov old, rax
545 2:
546 ; =r (old)
547 ; r (addr)
548 r (mask)
549 ; rdx
550 rax
551 rcx
552 memory
553 }
554 return old
555}
556
557// and_u64 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
558// The operation is performed with sequential consistency.
559// Panics if addr is not 8-byte aligned.
560pub fn and_u64(addr &u64, mask u64) u64 {
561 mut old := u64(0)
562 asm volatile amd64 {
563 mov rdx, addr
564 test rdx, 7
565 jz '1f'
566 call panicUnaligned
567 jmp '2f'
568 1:
569 3:
570 mov rax, [rdx]
571 mov rcx, rax
572 and rcx, mask
573 lock cmpxchg [rdx], rcx
574 jnz '3b'
575 mov old, rax
576 2:
577 ; =r (old)
578 ; r (addr)
579 r (mask)
580 ; rdx
581 rax
582 rcx
583 memory
584 }
585 return old
586}
587
588// or_i64 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
589// The operation is performed with sequential consistency.
590// Panics if addr is not 8-byte aligned.
591pub fn or_i64(addr &i64, mask i64) i64 {
592 mut old := i64(0)
593 asm volatile amd64 {
594 mov rdx, addr
595 test rdx, 7
596 jz '1f'
597 call panicUnaligned
598 jmp '2f'
599 1:
600 3:
601 mov rax, [rdx]
602 mov rcx, rax
603 or rcx, mask
604 lock cmpxchg [rdx], rcx
605 jnz '3b'
606 mov old, rax
607 2:
608 ; =r (old)
609 ; r (addr)
610 r (mask)
611 ; rdx
612 rax
613 rcx
614 memory
615 }
616 return old
617}
618
619// or_u64 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
620// The operation is performed with sequential consistency.
621// Panics if addr is not 8-byte aligned.
622pub fn or_u64(addr &u64, mask u64) u64 {
623 mut old := u64(0)
624 asm volatile amd64 {
625 mov rdx, addr
626 test rdx, 7
627 jz '1f'
628 call panicUnaligned
629 jmp '2f'
630 1:
631 3:
632 mov rax, [rdx]
633 mov rcx, rax
634 or rcx, mask
635 lock cmpxchg [rdx], rcx
636 jnz '3b'
637 mov old, rax
638 2:
639 ; =r (old)
640 ; r (addr)
641 r (mask)
642 ; rdx
643 rax
644 rcx
645 memory
646 }
647 return old
648}
649
650// and_i32 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
651// The operation is performed with sequential consistency.
652// Panics if addr is not 4-byte aligned.
653pub fn and_i32(addr &i32, mask i32) i32 {
654 mut old := i32(0)
655 asm volatile amd64 {
656 mov rdx, addr
657 test rdx, 3
658 jz '1f'
659 call panicUnaligned
660 jmp '2f'
661 1:
662 3:
663 mov eax, [rdx]
664 mov ecx, eax
665 and ecx, mask
666 lock cmpxchg [rdx], ecx
667 jnz '3b'
668 mov old, eax
669 2:
670 ; =r (old)
671 ; r (addr)
672 r (mask)
673 ; rdx
674 eax
675 ecx
676 memory
677 }
678 return old
679}
680
681// and_u32 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
682// The operation is performed with sequential consistency.
683// Panics if addr is not 4-byte aligned.
684pub fn and_u32(addr &u32, mask u32) u32 {
685 mut old := u32(0)
686 asm volatile amd64 {
687 mov rdx, addr
688 test rdx, 3
689 jz '1f'
690 call panicUnaligned
691 jmp '2f'
692 1:
693 3:
694 mov eax, [rdx]
695 mov ecx, eax
696 and ecx, mask
697 lock cmpxchg [rdx], ecx
698 jnz '3b'
699 mov old, eax
700 2:
701 ; =r (old)
702 ; r (addr)
703 r (mask)
704 ; rdx
705 eax
706 ecx
707 memory
708 }
709 return old
710}
711
712// or_i32 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
713// The operation is performed with sequential consistency.
714// Panics if addr is not 4-byte aligned.
715pub fn or_i32(addr &i32, mask i32) i32 {
716 mut old := i32(0)
717 asm volatile amd64 {
718 mov rdx, addr
719 test rdx, 3
720 jz '1f'
721 call panicUnaligned
722 jmp '2f'
723 1:
724 3:
725 mov eax, [rdx]
726 mov ecx, eax
727 or ecx, mask
728 lock cmpxchg [rdx], ecx
729 jnz '3b'
730 mov old, eax
731 2:
732 ; =r (old)
733 ; r (addr)
734 r (mask)
735 ; rdx
736 eax
737 ecx
738 memory
739 }
740 return old
741}
742
743// or_u32 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
744// The operation is performed with sequential consistency.
745// Panics if addr is not 4-byte aligned.
746pub fn or_u32(addr &u32, mask u32) u32 {
747 mut old := u32(0)
748 asm volatile amd64 {
749 mov rdx, addr
750 test rdx, 3
751 jz '1f'
752 call panicUnaligned
753 jmp '2f'
754 1:
755 3:
756 mov eax, [rdx]
757 mov ecx, eax
758 or ecx, mask
759 lock cmpxchg [rdx], ecx
760 jnz '3b'
761 mov old, eax
762 2:
763 ; =r (old)
764 ; r (addr)
765 r (mask)
766 ; rdx
767 eax
768 ecx
769 memory
770 }
771 return old
772}
773