First public contribution.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\common\x86\atomics.cia
18 #include <e32atomics.h>
23 WINS/WINSCW Use X86 locked operations. Assume Pentium or above CPU (CMPXCHG8B available)
24 X86 For Pentium and above use locked operations
25 For 486 use locked operations for 8, 16, 32 bit. For 64 bit must disable interrupts.
26 NOTE: 486 not supported at the moment
27 ARMv4/ARMv5 Must disable interrupts.
28 ARMv6 LDREX/STREX for 8, 16, 32 bit. For 64 bit must disable interrupts (maybe).
29 ARMv6K/ARMv7 LDREXB/LDREXH/LDREX/LDREXD
31 Need both kernel side and user side versions
34 #if defined(__SMP__) || !defined(__EPOC32__)
35 #define __BARRIERS_NEEDED__
36 #define __LOCK__ "lock "
51 #define __TUintX__ TUint32
52 #define __TIntX__ TInt32
53 #define __fname__(x) x##32
54 #define __redir__(x) asm("jmp _"#x "32")
55 #define __A_REG__ "eax"
56 #define __C_REG__ "ecx"
57 #define __D_REG__ "edx"
58 #include "atomic_skeleton.h"
67 #define __TUintX__ TUint16
68 #define __TIntX__ TInt16
69 #define __fname__(x) x##16
70 #define __redir__(x) asm("jmp _"#x "16")
71 #define __A_REG__ "ax"
72 #define __C_REG__ "cx"
73 #define __D_REG__ "dx"
74 #include "atomic_skeleton.h"
83 #define __TUintX__ TUint8
84 #define __TIntX__ TInt8
85 #define __fname__(x) x##8
86 #define __redir__(x) asm("jmp _"#x "8")
87 #define __A_REG__ "al"
88 #define __C_REG__ "cl"
89 #define __D_REG__ "dl"
90 #include "atomic_skeleton.h"
100 /** Full memory barrier for explicit memory accesses
103 EXPORT_C __NAKED__ void __e32_memory_barrier()
105 #ifdef __BARRIERS_NEEDED__
106 asm("lock add dword ptr [esp], 0 ");
112 /** Barrier guaranteeing completion as well as ordering
115 EXPORT_C __NAKED__ void __e32_io_completion_barrier()
124 /** Find the most significant 1 in a 32 bit word
126 @param v The word to be scanned
127 @return The bit number of the most significant 1 if v != 0
130 EXPORT_C __NAKED__ TInt __e32_find_ms1_32(TUint32 /*v*/)
132 asm("bsr eax, [esp+4] ");
133 asm("jnz short 1f ");
134 asm("mov eax, 0xffffffff ");
140 /** Find the least significant 1 in a 32 bit word
142 @param v The word to be scanned
143 @return The bit number of the least significant 1 if v != 0
146 EXPORT_C __NAKED__ TInt __e32_find_ls1_32(TUint32 /*v*/)
148 asm("bsf eax, [esp+4] ");
149 asm("jnz short 1f ");
150 asm("mov eax, 0xffffffff ");
156 /** Count the number of 1's in a 32 bit word
158 @param v The word to be scanned
159 @return The number of 1's
161 EXPORT_C __NAKED__ TInt __e32_bit_count_32(TUint32 /*v*/)
163 asm("mov eax, [esp+4] ");
164 asm("mov edx, eax ");
165 asm("and eax, 0xaaaaaaaa ");
166 asm("and edx, 0x55555555 "); /* edx = even bits of arg */
167 asm("shr eax, 1 "); /* eax = odd bits of arg shifted into even bits */
168 asm("add eax, edx "); /* eax = 16 groups of 2 bit counts */
169 asm("mov edx, eax ");
170 asm("and eax, 0xcccccccc ");
171 asm("and edx, 0x33333333 "); /* even groups of 2 */
172 asm("shr eax, 2 "); /* odd groups of 2 shifted to even positions */
173 asm("add eax, edx "); /* 8 groups of 4 bit counts */
174 asm("mov edx, eax ");
176 asm("add eax, edx "); /* even nibbles = sum of 8 bits, odd nibbles garbage */
177 asm("and eax, 0x0f0f0f0f "); /* eliminate garbage nibbles */
178 asm("add al, ah "); /* AL = bit count of lower 16 bits */
181 asm("add al, ah "); /* AL = bit count of upper 16 bits */
182 asm("xor ah, ah "); /* top 24 bits of EAX now zero */
183 asm("add al, dl "); /* AL = bit count of entire 32 bits */
188 /** Find the most significant 1 in a 64 bit word
190 @param v The word to be scanned
191 @return The bit number of the most significant 1 if v != 0
194 EXPORT_C __NAKED__ TInt __e32_find_ms1_64(TUint64 /*v*/)
196 asm("bsr eax, [esp+8] ");
197 asm("jnz short 2f ");
198 asm("bsr eax, [esp+4] ");
199 asm("jnz short 1f ");
200 asm("mov eax, 0xffffffff ");
208 /** Find the least significant 1 in a 64 bit word
210 @param v The word to be scanned
211 @return The bit number of the least significant 1 if v != 0
214 EXPORT_C __NAKED__ TInt __e32_find_ls1_64(TUint64 /*v*/)
216 asm("bsf eax, [esp+4] ");
217 asm("jnz short 1f ");
218 asm("bsf eax, [esp+8] ");
219 asm("jnz short 2f ");
220 asm("mov eax, 0xffffffff ");
228 /** Count the number of 1's in a 64 bit word
230 @param v The word to be scanned
231 @return The number of 1's
233 EXPORT_C __NAKED__ TInt __e32_bit_count_64(TUint64 /*v*/)
235 asm("mov eax, [esp+4] ");
236 asm("mov edx, [esp+8] ");
238 asm("mov ecx, eax ");
239 asm("and eax, 0xaaaaaaaa ");
240 asm("and ecx, 0x55555555 ");
242 asm("add eax, ecx ");
243 asm("mov ecx, eax ");
244 asm("and eax, 0xcccccccc ");
245 asm("and ecx, 0x33333333 ");
247 asm("add ecx, eax ");
249 asm("mov eax, edx ");
250 asm("and eax, 0xaaaaaaaa ");
251 asm("and edx, 0x55555555 ");
253 asm("add eax, edx ");
254 asm("mov edx, eax ");
255 asm("and eax, 0xcccccccc ");
256 asm("and edx, 0x33333333 ");
258 asm("add eax, edx ");
260 asm("add eax, ecx ");
261 asm("mov edx, eax ");
262 asm("and eax, 0xf0f0f0f0 ");
263 asm("and edx, 0x0f0f0f0f ");
265 asm("add eax, edx ");
278 /** Read a 64 bit word with acquire semantics
280 @param a Address of word to be read - must be a multiple of 8
281 @return The value read
283 EXPORT_C __NAKED__ TUint64 __e32_atomic_load_acq64(const volatile TAny* /*a*/)
287 asm("mov edi, [esp+12] ");
288 asm("mov eax, 0x0badbeef ");
289 asm("mov edx, eax ");
290 asm("mov ebx, eax ");
291 asm("mov ecx, eax ");
292 asm(__LOCK__ "cmpxchg8b [edi] ");
299 /** Write a 64 bit word with release semantics
301 @param a Address of word to be written - must be a multiple of 8
302 @param v The value to be written
303 @return The value written
305 EXPORT_C __NAKED__ TUint64 __e32_atomic_store_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
309 asm("mov edi, [esp+12] ");
310 asm("mov ebx, [esp+16] ");
311 asm("mov ecx, [esp+20] ");
312 asm("mov eax, [edi] ");
313 asm("mov edx, [edi+4] ");
315 asm(__LOCK__ "cmpxchg8b [edi] " );
316 asm("jne short 1b ");
317 asm("mov eax, ebx ");
318 asm("mov edx, ecx ");
325 /** Write a 64 bit word with full barrier semantics
327 @param a Address of word to be written - must be a multiple of 8
328 @param v The value to be written
329 @return The value written
331 EXPORT_C __NAKED__ TUint64 __e32_atomic_store_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
333 asm("jmp ___e32_atomic_store_rel64 ");
337 /** Write a 64 bit word to memory and return the original value of the memory.
340 @param a Address of word to be written - must be a multiple of 8
341 @param v The value to be written
342 @return The original value of *a
344 EXPORT_C __NAKED__ TUint64 __e32_atomic_swp_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
346 asm("jmp ___e32_atomic_swp_ord64 ");
350 /** Write a 64 bit word to memory and return the original value of the memory.
353 @param a Address of word to be written - must be a multiple of 8
354 @param v The value to be written
355 @return The original value of *a
357 EXPORT_C __NAKED__ TUint64 __e32_atomic_swp_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
359 asm("jmp ___e32_atomic_swp_ord64 ");
363 /** Write a 64 bit word to memory and return the original value of the memory.
366 @param a Address of word to be written - must be a multiple of 8
367 @param v The value to be written
368 @return The original value of *a
370 EXPORT_C __NAKED__ TUint64 __e32_atomic_swp_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
372 asm("jmp ___e32_atomic_swp_ord64 ");
376 /** Write a 64 bit word to memory and return the original value of the memory.
377 Full barrier semantics.
379 @param a Address of word to be written - must be a multiple of 8
380 @param v The value to be written
381 @return The original value of *a
383 EXPORT_C __NAKED__ TUint64 __e32_atomic_swp_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
387 asm("mov edi, [esp+12] ");
388 asm("mov ebx, [esp+16] ");
389 asm("mov ecx, [esp+20] ");
390 asm("mov eax, [edi] ");
391 asm("mov edx, [edi+4] ");
393 asm(__LOCK__ "cmpxchg8b [edi] ");
394 asm("jne short 1b ");
401 /** 64 bit compare and swap, relaxed ordering.
403 Atomically performs the following operation:
404 if (*a == *q) { *a = v; return TRUE; }
405 else { *q = *a; return FALSE; }
407 @param a Address of word to be written - must be a multiple of 8
408 @param q Address of location containing expected value
409 @param v The new value to be written if the old value is as expected
410 @return TRUE if *a was updated, FALSE otherwise
412 EXPORT_C __NAKED__ TBool __e32_atomic_cas_rlx64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
414 asm("jmp ___e32_atomic_cas_ord64 ");
418 /** 64 bit compare and swap, acquire semantics.
420 Atomically performs the following operation:
421 if (*a == *q) { *a = v; return TRUE; }
422 else { *q = *a; return FALSE; }
424 @param a Address of word to be written - must be a multiple of 8
425 @param q Address of location containing expected value
426 @param v The new value to be written if the old value is as expected
427 @return TRUE if *a was updated, FALSE otherwise
429 EXPORT_C __NAKED__ TBool __e32_atomic_cas_acq64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
431 asm("jmp ___e32_atomic_cas_ord64 ");
435 /** 64 bit compare and swap, release semantics.
437 Atomically performs the following operation:
438 if (*a == *q) { *a = v; return TRUE; }
439 else { *q = *a; return FALSE; }
441 @param a Address of word to be written - must be a multiple of 8
442 @param q Address of location containing expected value
443 @param v The new value to be written if the old value is as expected
444 @return TRUE if *a was updated, FALSE otherwise
446 EXPORT_C __NAKED__ TBool __e32_atomic_cas_rel64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
448 asm("jmp ___e32_atomic_cas_ord64 ");
452 /** 64 bit compare and swap, full barrier semantics.
454 Atomically performs the following operation:
455 if (*a == *q) { *a = v; return TRUE; }
456 else { *q = *a; return FALSE; }
458 @param a Address of word to be written - must be a multiple of 8
459 @param q Address of location containing expected value
460 @param v The new value to be written if the old value is as expected
461 @return TRUE if *a was updated, FALSE otherwise
463 EXPORT_C __NAKED__ TBool __e32_atomic_cas_ord64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
468 asm("mov edi, [esp+16] "); // edi = a
469 asm("mov esi, [esp+20] "); // esi = q
470 asm("mov ebx, [esp+24] "); // ecx:ebx = v
471 asm("mov ecx, [esp+28] ");
472 asm("mov eax, [esi] "); // edx:eax = *q
473 asm("mov edx, [esi+4] ");
474 asm(__LOCK__ "cmpxchg8b [edi] "); // if (*a==*q) *a=v, ZF=1 else edx:eax=*a, ZF=0
475 asm("jne short 2f ");
482 asm("mov [esi], eax "); // *q = edx:eax
483 asm("mov [esi+4], edx ");
484 asm("xor eax, eax ");
492 /** 64 bit atomic add, relaxed ordering.
494 Atomically performs the following operation:
495 oldv = *a; *a = oldv + v; return oldv;
497 @param a Address of word to be updated - must be a multiple of 8
498 @param v The value to be added
499 @return The original value of *a
501 EXPORT_C __NAKED__ TUint64 __e32_atomic_add_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
503 asm("jmp ___e32_atomic_add_ord64 ");
507 /** 64 bit atomic add, acquire semantics.
509 Atomically performs the following operation:
510 oldv = *a; *a = oldv + v; return oldv;
512 @param a Address of word to be updated - must be a multiple of 8
513 @param v The value to be added
514 @return The original value of *a
516 EXPORT_C __NAKED__ TUint64 __e32_atomic_add_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
518 asm("jmp ___e32_atomic_add_ord64 ");
522 /** 64 bit atomic add, release semantics.
524 Atomically performs the following operation:
525 oldv = *a; *a = oldv + v; return oldv;
527 @param a Address of word to be updated - must be a multiple of 8
528 @param v The value to be added
529 @return The original value of *a
531 EXPORT_C __NAKED__ TUint64 __e32_atomic_add_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
533 asm("jmp ___e32_atomic_add_ord64 ");
537 /** 64 bit atomic add, full barrier semantics.
539 Atomically performs the following operation:
540 oldv = *a; *a = oldv + v; return oldv;
542 @param a Address of word to be updated - must be a multiple of 8
543 @param v The value to be added
544 @return The original value of *a
546 EXPORT_C __NAKED__ TUint64 __e32_atomic_add_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
550 asm("mov edi, [esp+12] "); // edi = a
551 asm("mov eax, [edi] "); // edx:eax = oldv
552 asm("mov edx, [edi+4] ");
554 asm("mov ebx, eax ");
555 asm("mov ecx, edx ");
556 asm("add ebx, [esp+16] "); // ecx:ebx = oldv + v
557 asm("adc ecx, [esp+20] ");
558 asm(__LOCK__ "cmpxchg8b [edi] "); // if (*a==oldv) *a=oldv+v, ZF=1 else edx:eax=*a, ZF=0
559 asm("jne short 1b ");
566 /** 64 bit atomic bitwise logical AND, relaxed ordering.
568 Atomically performs the following operation:
569 oldv = *a; *a = oldv & v; return oldv;
571 @param a Address of word to be updated - must be a multiple of 8
572 @param v The value to be ANDed with *a
573 @return The original value of *a
575 EXPORT_C __NAKED__ TUint64 __e32_atomic_and_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
577 asm("jmp ___e32_atomic_and_ord64 ");
581 /** 64 bit atomic bitwise logical AND, acquire semantics.
583 Atomically performs the following operation:
584 oldv = *a; *a = oldv & v; return oldv;
586 @param a Address of word to be updated - must be a multiple of 8
587 @param v The value to be ANDed with *a
588 @return The original value of *a
590 EXPORT_C __NAKED__ TUint64 __e32_atomic_and_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
592 asm("jmp ___e32_atomic_and_ord64 ");
596 /** 64 bit atomic bitwise logical AND, release semantics.
598 Atomically performs the following operation:
599 oldv = *a; *a = oldv & v; return oldv;
601 @param a Address of word to be updated - must be a multiple of 8
602 @param v The value to be ANDed with *a
603 @return The original value of *a
605 EXPORT_C __NAKED__ TUint64 __e32_atomic_and_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
607 asm("jmp ___e32_atomic_and_ord64 ");
611 /** 64 bit atomic bitwise logical AND, full barrier semantics.
613 Atomically performs the following operation:
614 oldv = *a; *a = oldv & v; return oldv;
616 @param a Address of word to be updated - must be a multiple of 8
617 @param v The value to be ANDed with *a
618 @return The original value of *a
620 EXPORT_C __NAKED__ TUint64 __e32_atomic_and_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
624 asm("mov edi, [esp+12] "); // edi = a
625 asm("mov eax, [edi] "); // edx:eax = oldv
626 asm("mov edx, [edi+4] ");
628 asm("mov ebx, eax ");
629 asm("mov ecx, edx ");
630 asm("and ebx, [esp+16] "); // ecx:ebx = oldv & v
631 asm("and ecx, [esp+20] ");
632 asm(__LOCK__ "cmpxchg8b [edi] "); // if (*a==oldv) *a=oldv&v, ZF=1 else edx:eax=*a, ZF=0
633 asm("jne short 1b ");
640 /** 64 bit atomic bitwise logical inclusive OR, relaxed ordering.
642 Atomically performs the following operation:
643 oldv = *a; *a = oldv | v; return oldv;
645 @param a Address of word to be updated - must be a multiple of 8
646 @param v The value to be ORed with *a
647 @return The original value of *a
649 EXPORT_C __NAKED__ TUint64 __e32_atomic_ior_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
651 asm("jmp ___e32_atomic_ior_ord64 ");
655 /** 64 bit atomic bitwise logical inclusive OR, acquire semantics.
657 Atomically performs the following operation:
658 oldv = *a; *a = oldv | v; return oldv;
660 @param a Address of word to be updated - must be a multiple of 8
661 @param v The value to be ORed with *a
662 @return The original value of *a
664 EXPORT_C __NAKED__ TUint64 __e32_atomic_ior_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
666 asm("jmp ___e32_atomic_ior_ord64 ");
670 /** 64 bit atomic bitwise logical inclusive OR, release semantics.
672 Atomically performs the following operation:
673 oldv = *a; *a = oldv | v; return oldv;
675 @param a Address of word to be updated - must be a multiple of 8
676 @param v The value to be ORed with *a
677 @return The original value of *a
679 EXPORT_C __NAKED__ TUint64 __e32_atomic_ior_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
681 asm("jmp ___e32_atomic_ior_ord64 ");
685 /** 64 bit atomic bitwise logical inclusive OR, full barrier semantics.
687 Atomically performs the following operation:
688 oldv = *a; *a = oldv | v; return oldv;
690 @param a Address of word to be updated - must be a multiple of 8
691 @param v The value to be ORed with *a
692 @return The original value of *a
694 EXPORT_C __NAKED__ TUint64 __e32_atomic_ior_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
698 asm("mov edi, [esp+12] "); // edi = a
699 asm("mov eax, [edi] "); // edx:eax = oldv
700 asm("mov edx, [edi+4] ");
702 asm("mov ebx, eax ");
703 asm("mov ecx, edx ");
704 asm("or ebx, [esp+16] "); // ecx:ebx = oldv | v
705 asm("or ecx, [esp+20] ");
706 asm(__LOCK__ "cmpxchg8b [edi] "); // if (*a==oldv) *a=oldv|v, ZF=1 else edx:eax=*a, ZF=0
707 asm("jne short 1b ");
714 /** 64 bit atomic bitwise logical exclusive OR, relaxed ordering.
716 Atomically performs the following operation:
717 oldv = *a; *a = oldv ^ v; return oldv;
719 @param a Address of word to be updated - must be a multiple of 8
720 @param v The value to be XORed with *a
721 @return The original value of *a
723 EXPORT_C __NAKED__ TUint64 __e32_atomic_xor_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
725 asm("jmp ___e32_atomic_xor_ord64 ");
729 /** 64 bit atomic bitwise logical exclusive OR, acquire semantics.
731 Atomically performs the following operation:
732 oldv = *a; *a = oldv ^ v; return oldv;
734 @param a Address of word to be updated - must be a multiple of 8
735 @param v The value to be XORed with *a
736 @return The original value of *a
738 EXPORT_C __NAKED__ TUint64 __e32_atomic_xor_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
740 asm("jmp ___e32_atomic_xor_ord64 ");
744 /** 64 bit atomic bitwise logical exclusive OR, release semantics.
746 Atomically performs the following operation:
747 oldv = *a; *a = oldv ^ v; return oldv;
749 @param a Address of word to be updated - must be a multiple of 8
750 @param v The value to be XORed with *a
751 @return The original value of *a
753 EXPORT_C __NAKED__ TUint64 __e32_atomic_xor_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
755 asm("jmp ___e32_atomic_xor_ord64 ");
759 /** 64 bit atomic bitwise logical exclusive OR, full barrier semantics.
761 Atomically performs the following operation:
762 oldv = *a; *a = oldv ^ v; return oldv;
764 @param a Address of word to be updated - must be a multiple of 8
765 @param v The value to be XORed with *a
766 @return The original value of *a
768 EXPORT_C __NAKED__ TUint64 __e32_atomic_xor_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
772 asm("mov edi, [esp+12] "); // edi = a
773 asm("mov eax, [edi] "); // edx:eax = oldv
774 asm("mov edx, [edi+4] ");
776 asm("mov ebx, eax ");
777 asm("mov ecx, edx ");
778 asm("xor ebx, [esp+16] "); // ecx:ebx = oldv ^ v
779 asm("xor ecx, [esp+20] ");
780 asm(__LOCK__ "cmpxchg8b [edi] "); // if (*a==oldv) *a=oldv^v, ZF=1 else edx:eax=*a, ZF=0
781 asm("jne short 1b ");
788 /** 64 bit atomic bitwise universal function, relaxed ordering.
790 Atomically performs the following operation:
791 oldv = *a; *a = (oldv & u) ^ v; return oldv;
793 @param a Address of word to be updated - must be a multiple of 8
794 @param u The value to be ANDed with *a
795 @param v The value to be XORed with (*a&u)
796 @return The original value of *a
798 EXPORT_C __NAKED__ TUint64 __e32_atomic_axo_rlx64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
800 asm("jmp ___e32_atomic_axo_ord64 ");
804 /** 64 bit atomic bitwise universal function, acquire semantics.
806 Atomically performs the following operation:
807 oldv = *a; *a = (oldv & u) ^ v; return oldv;
809 @param a Address of word to be updated - must be a multiple of 8
810 @param u The value to be ANDed with *a
811 @param v The value to be XORed with (*a&u)
812 @return The original value of *a
814 EXPORT_C __NAKED__ TUint64 __e32_atomic_axo_acq64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
816 asm("jmp ___e32_atomic_axo_ord64 ");
820 /** 64 bit atomic bitwise universal function, release semantics.
822 Atomically performs the following operation:
823 oldv = *a; *a = (oldv & u) ^ v; return oldv;
825 @param a Address of word to be updated - must be a multiple of 8
826 @param u The value to be ANDed with *a
827 @param v The value to be XORed with (*a&u)
828 @return The original value of *a
830 EXPORT_C __NAKED__ TUint64 __e32_atomic_axo_rel64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
832 asm("jmp ___e32_atomic_axo_ord64 ");
836 /** 64 bit atomic bitwise universal function, release semantics.
838 Atomically performs the following operation:
839 oldv = *a; *a = (oldv & u) ^ v; return oldv;
841 @param a Address of word to be updated - must be a multiple of 8
842 @param u The value to be ANDed with *a
843 @param v The value to be XORed with (*a&u)
844 @return The original value of *a
846 EXPORT_C __NAKED__ TUint64 __e32_atomic_axo_ord64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
850 asm("mov edi, [esp+12] "); // edi = a
851 asm("mov eax, [edi] "); // edx:eax = oldv
852 asm("mov edx, [edi+4] ");
854 asm("mov ebx, eax ");
855 asm("mov ecx, edx ");
856 asm("and ebx, [esp+16] "); // ecx:ebx = oldv & u
857 asm("and ecx, [esp+20] ");
858 asm("xor ebx, [esp+24] "); // ecx:ebx = (oldv & u) ^ v
859 asm("xor ecx, [esp+28] ");
860 asm(__LOCK__ "cmpxchg8b [edi] "); // if (*a==oldv) *a=(oldv&u)^v, ZF=1 else edx:eax=*a, ZF=0
861 asm("jne short 1b ");
868 /** 64 bit threshold and add, unsigned, relaxed ordering.
870 Atomically performs the following operation:
871 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
873 @param a Address of data to be updated - must be naturally aligned
874 @param t The threshold to compare *a to (unsigned compare)
875 @param u The value to be added to *a if it is originally >= t
876 @param u The value to be added to *a if it is originally < t
877 @return The original value of *a
879 EXPORT_C __NAKED__ TUint64 __e32_atomic_tau_rlx64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
881 asm("jmp ___e32_atomic_tau_ord64 ");
885 /** 64 bit threshold and add, unsigned, acquire semantics.
887 Atomically performs the following operation:
888 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
890 @param a Address of data to be updated - must be naturally aligned
891 @param t The threshold to compare *a to (unsigned compare)
892 @param u The value to be added to *a if it is originally >= t
893 @param u The value to be added to *a if it is originally < t
894 @return The original value of *a
896 EXPORT_C __NAKED__ TUint64 __e32_atomic_tau_acq64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
898 asm("jmp ___e32_atomic_tau_ord64 ");
902 /** 64 bit threshold and add, unsigned, release semantics.
904 Atomically performs the following operation:
905 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
907 @param a Address of data to be updated - must be naturally aligned
908 @param t The threshold to compare *a to (unsigned compare)
909 @param u The value to be added to *a if it is originally >= t
910 @param u The value to be added to *a if it is originally < t
911 @return The original value of *a
913 EXPORT_C __NAKED__ TUint64 __e32_atomic_tau_rel64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
915 asm("jmp ___e32_atomic_tau_ord64 ");
919 /** 64 bit threshold and add, unsigned, full barrier semantics.
921 Atomically performs the following operation:
922 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
924 @param a Address of data to be updated - must be naturally aligned
925 @param t The threshold to compare *a to (unsigned compare)
926 @param u The value to be added to *a if it is originally >= t
927 @param u The value to be added to *a if it is originally < t
928 @return The original value of *a
930 EXPORT_C __NAKED__ TUint64 __e32_atomic_tau_ord64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
934 asm("mov edi, [esp+12] "); // edi = a
935 asm("mov eax, [edi] "); // edx:eax = oldv
936 asm("mov edx, [edi+4] ");
938 asm("mov ebx, edx ");
939 asm("cmp eax, [esp+16] "); // eax - t.low, CF=borrow
940 asm("sbb ebx, [esp+20] "); // CF = borrow from (oldv - t)
941 asm("jnc short 2f "); // no borrow means oldv>=t so use u
942 asm("mov ebx, [esp+32] "); // ecx:ebx = v
943 asm("mov ecx, [esp+36] ");
944 asm("jmp short 3f ");
946 asm("mov ebx, [esp+24] "); // ecx:ebx = u
947 asm("mov ecx, [esp+28] ");
949 asm("add ebx, eax "); // ecx:ebx = oldv + u or v
950 asm("adc ecx, edx ");
951 asm(__LOCK__ "cmpxchg8b [edi] ");
952 asm("jne short 1b ");
959 /** 64 bit threshold and add, signed, relaxed ordering.
961 Atomically performs the following operation:
962 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
964 @param a Address of data to be updated - must be naturally aligned
965 @param t The threshold to compare *a to (signed compare)
966 @param u The value to be added to *a if it is originally >= t
967 @param u The value to be added to *a if it is originally < t
968 @return The original value of *a
970 EXPORT_C __NAKED__ TInt64 __e32_atomic_tas_rlx64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
972 asm("jmp ___e32_atomic_tas_ord64 ");
976 /** 64 bit threshold and add, signed, acquire semantics.
978 Atomically performs the following operation:
979 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
981 @param a Address of data to be updated - must be naturally aligned
982 @param t The threshold to compare *a to (signed compare)
983 @param u The value to be added to *a if it is originally >= t
984 @param u The value to be added to *a if it is originally < t
985 @return The original value of *a
987 EXPORT_C __NAKED__ TInt64 __e32_atomic_tas_acq64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
989 asm("jmp ___e32_atomic_tas_ord64 ");
993 /** 64 bit threshold and add, signed, release semantics.
995 Atomically performs the following operation:
996 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
998 @param a Address of data to be updated - must be naturally aligned
999 @param t The threshold to compare *a to (signed compare)
1000 @param u The value to be added to *a if it is originally >= t
1001 @param u The value to be added to *a if it is originally < t
1002 @return The original value of *a
1004 EXPORT_C __NAKED__ TInt64 __e32_atomic_tas_rel64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
1006 asm("jmp ___e32_atomic_tas_ord64 ");
1010 /** 64 bit threshold and add, signed, full barrier semantics.
1012 Atomically performs the following operation:
1013 oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
1015 @param a Address of data to be updated - must be naturally aligned
1016 @param t The threshold to compare *a to (signed compare)
1017 @param u The value to be added to *a if it is originally >= t
1018 @param u The value to be added to *a if it is originally < t
1019 @return The original value of *a
1021 EXPORT_C __NAKED__ TInt64 __e32_atomic_tas_ord64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
1025 asm("mov edi, [esp+12] "); // edi = a
1026 asm("mov eax, [edi] "); // edx:eax = oldv
1027 asm("mov edx, [edi+4] ");
1029 asm("mov ebx, edx ");
1030 asm("cmp eax, [esp+16] "); // eax - t.low, CF=borrow
1031 asm("sbb ebx, [esp+20] "); // SF=sign, OF=overflow from (oldv - t)
1032 asm("jge short 2f "); // SF==OF (GE condition) means oldv>=t so use u
1033 asm("mov ebx, [esp+32] "); // ecx:ebx = v
1034 asm("mov ecx, [esp+36] ");
1035 asm("jmp short 3f ");
1037 asm("mov ebx, [esp+24] "); // ecx:ebx = u
1038 asm("mov ecx, [esp+28] ");
1040 asm("add ebx, eax "); // ecx:ebx = oldv + u or v
1041 asm("adc ecx, edx ");
1042 asm(__LOCK__ "cmpxchg8b [edi] ");
1043 asm("jne short 1b ");