os/kernelhwsrv/kernel/eka/common/win32/atomics.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\common\x86\atomics.cpp
    15 // 
    16 //
    17 
    18 #include <e32atomics.h>
    19 #include <cpudefs.h>
    20 
    21 /*
    22 Versions needed:
    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
    30 
    31 Need both kernel side and user side versions
    32 */
    33 
    34 #if	defined(__SMP__) || !defined(__EPOC32__)
    35 #define	__BARRIERS_NEEDED__
    36 #define	__LOCK__	lock
    37 #else
    38 #define	__LOCK__
    39 #endif
    40 
    41 
    42 extern "C" {
    43 
    44 #undef	__TUintX__
    45 #undef	__TIntX__
    46 #undef	__fname__
    47 #undef	__A_REG__
    48 #undef	__C_REG__
    49 #undef	__D_REG__
    50 #define	__TUintX__		TUint32
    51 #define	__TIntX__		TInt32
    52 #define	__fname__(x)	x##32
    53 #define	__A_REG__		eax
    54 #define	__C_REG__		ecx
    55 #define	__D_REG__		edx
    56 #include "atomic_skeleton.h"
    57 
    58 #undef	__TUintX__
    59 #undef	__TIntX__
    60 #undef	__fname__
    61 #undef	__A_REG__
    62 #undef	__C_REG__
    63 #undef	__D_REG__
    64 #define	__TUintX__		TUint16
    65 #define	__TIntX__		TInt16
    66 #define	__fname__(x)	x##16
    67 #define	__A_REG__		ax
    68 #define	__C_REG__		cx
    69 #define	__D_REG__		dx
    70 #include "atomic_skeleton.h"
    71 
    72 #undef	__TUintX__
    73 #undef	__TIntX__
    74 #undef	__fname__
    75 #undef	__A_REG__
    76 #undef	__C_REG__
    77 #undef	__D_REG__
    78 #define	__TUintX__		TUint8
    79 #define	__TIntX__		TInt8
    80 #define	__fname__(x)	x##8
    81 #define	__A_REG__		al
    82 #define	__C_REG__		cl
    83 #define	__D_REG__		dl
    84 #include "atomic_skeleton.h"
    85 
    86 #undef	__TUintX__
    87 #undef	__TIntX__
    88 #undef	__fname__
    89 #undef	__A_REG__
    90 #undef	__C_REG__
    91 #undef	__D_REG__
    92 
    93 /** Full memory barrier for explicit memory accesses
    94 
    95 */
    96 EXPORT_C __NAKED__ void __e32_memory_barrier()
    97 	{
    98 #ifdef __BARRIERS_NEEDED__
    99 	_asm lock add dword ptr [esp], 0
   100 #endif
   101 	_asm ret
   102 	}
   103 
   104 
   105 /** Barrier guaranteeing completion as well as ordering
   106 
   107 */
   108 EXPORT_C __NAKED__ void __e32_io_completion_barrier()
   109 	{
   110 	_asm push ebx
   111 	_asm cpuid
   112 	_asm pop ebx
   113 	_asm ret
   114 	}
   115 
   116 
   117 /** Find the most significant 1 in a 32 bit word
   118 
   119 	@param	v	The word to be scanned
   120 	@return		The bit number of the most significant 1 if v != 0
   121 				-1 if v == 0
   122 */
   123 EXPORT_C __NAKED__ TInt __e32_find_ms1_32(TUint32 /*v*/)
   124 	{
   125 	_asm bsr eax, [esp+4]
   126 	_asm jnz short done
   127 	_asm mov eax, 0ffffffffh
   128 done:
   129 	_asm ret
   130 	}
   131 
   132 
   133 /** Find the least significant 1 in a 32 bit word
   134 
   135 	@param	v	The word to be scanned
   136 	@return		The bit number of the least significant 1 if v != 0
   137 				-1 if v == 0
   138 */
   139 EXPORT_C __NAKED__ TInt __e32_find_ls1_32(TUint32 /*v*/)
   140 	{
   141 	_asm bsf eax, [esp+4]
   142 	_asm jnz short done
   143 	_asm mov eax, 0ffffffffh
   144 done:
   145 	_asm ret
   146 	}
   147 
   148 
   149 /** Count the number of 1's in a 32 bit word
   150 
   151 	@param	v	The word to be scanned
   152 	@return		The number of 1's
   153 */
   154 EXPORT_C __NAKED__ TInt __e32_bit_count_32(TUint32 /*v*/)
   155 	{
   156 	_asm mov eax, [esp+4]
   157 	_asm mov edx, eax
   158 	_asm and eax, 0aaaaaaaah
   159 	_asm and edx, 055555555h
   160 	_asm shr eax, 1
   161 	_asm add eax, edx
   162 	_asm mov edx, eax
   163 	_asm and eax, 0cccccccch
   164 	_asm and edx, 033333333h
   165 	_asm shr eax, 2
   166 	_asm add eax, edx
   167 	_asm mov edx, eax
   168 	_asm shr eax, 4
   169 	_asm add eax, edx
   170 	_asm and eax, 00f0f0f0fh
   171 	_asm add al, ah
   172 	_asm mov dl, al
   173 	_asm shr eax, 16
   174 	_asm add al, ah
   175 	_asm xor ah, ah
   176 	_asm add al, dl
   177 	_asm ret
   178 	}
   179 
   180 
   181 /** Find the most significant 1 in a 64 bit word
   182 
   183 	@param	v	The word to be scanned
   184 	@return		The bit number of the most significant 1 if v != 0
   185 				-1 if v == 0
   186 */
   187 EXPORT_C __NAKED__ TInt __e32_find_ms1_64(TUint64 /*v*/)
   188 	{
   189 	_asm bsr eax, [esp+8]
   190 	_asm jnz short mswnz
   191 	_asm bsr eax, [esp+4]
   192 	_asm jnz short lswnz
   193 	_asm mov eax, 0ffffffffh
   194 mswnz:
   195 	_asm or eax, 32
   196 lswnz:
   197 	_asm ret
   198 	}
   199 
   200 
   201 /** Find the least significant 1 in a 64 bit word
   202 
   203 	@param	v	The word to be scanned
   204 	@return		The bit number of the least significant 1 if v != 0
   205 				-1 if v == 0
   206 */
   207 EXPORT_C __NAKED__ TInt __e32_find_ls1_64(TUint64 /*v*/)
   208 	{
   209 	_asm bsf eax, [esp+4]
   210 	_asm jnz short lswnz
   211 	_asm bsf eax, [esp+8]
   212 	_asm jnz short mswnz
   213 	_asm mov eax, 0ffffffffh
   214 mswnz:
   215 	_asm or eax, 32
   216 lswnz:
   217 	_asm ret
   218 	}
   219 
   220 
   221 /** Count the number of 1's in a 64 bit word
   222 
   223 	@param	v	The word to be scanned
   224 	@return		The number of 1's
   225 */
   226 EXPORT_C __NAKED__ TInt __e32_bit_count_64(TUint64 /*v*/)
   227 	{
   228 	_asm mov eax, [esp+4]
   229 	_asm mov edx, [esp+8]
   230 
   231 	_asm mov ecx, eax
   232 	_asm and eax, 0aaaaaaaah
   233 	_asm and ecx, 055555555h
   234 	_asm shr eax, 1
   235 	_asm add eax, ecx			/* 16 groups of 2 bits, count=0,1,2 */
   236 	_asm mov ecx, eax
   237 	_asm and eax, 0cccccccch
   238 	_asm and ecx, 033333333h
   239 	_asm shr eax, 2
   240 	_asm add ecx, eax			/* 8 groups of 4 bits, count=0...4 */
   241 
   242 	_asm mov eax, edx
   243 	_asm and eax, 0aaaaaaaah
   244 	_asm and edx, 055555555h
   245 	_asm shr eax, 1
   246 	_asm add eax, edx			/* 16 groups of 2 bits, count=0,1,2 */
   247 	_asm mov edx, eax
   248 	_asm and eax, 0cccccccch
   249 	_asm and edx, 033333333h
   250 	_asm shr eax, 2
   251 	_asm add eax, edx			/* 8 groups of 4 bits, count=0...4 */
   252 
   253 	_asm add eax, ecx			/* 8 groups of 4 bits, count=0...8 */
   254 	_asm mov edx, eax
   255 	_asm and eax, 0f0f0f0f0h
   256 	_asm and edx, 00f0f0f0fh
   257 	_asm shr eax, 4
   258 	_asm add eax, edx			/* 4 groups of 8 bits, count=0...16 */
   259 	_asm add al, ah
   260 	_asm mov dl, al
   261 	_asm shr eax, 16
   262 	_asm add al, ah
   263 	_asm xor ah, ah
   264 	_asm add al, dl
   265 	_asm ret
   266 	}
   267 
   268 
   269 
   270 
   271 /** Read a 64 bit word with acquire semantics
   272 
   273 	@param	a	Address of word to be read - must be a multiple of 8
   274 	@return		The value read
   275 */
   276 EXPORT_C __NAKED__ TUint64	__e32_atomic_load_acq64(const volatile TAny* /*a*/)
   277 	{
   278 	_asm push ebx
   279 	_asm push edi
   280 	_asm mov edi, [esp+12]
   281 	_asm mov eax, 0badbeefh
   282 	_asm mov edx, eax
   283 	_asm mov ebx, eax
   284 	_asm mov ecx, eax
   285 	_asm __LOCK__ cmpxchg8b [edi]
   286 	_asm pop edi
   287 	_asm pop ebx
   288 	_asm ret
   289 	}
   290 
   291 
   292 /** Write a 64 bit word with release semantics
   293 
   294 	@param	a	Address of word to be written - must be a multiple of 8
   295 	@param	v	The value to be written
   296 	@return		The value written
   297 */
   298 EXPORT_C __NAKED__ TUint64	__e32_atomic_store_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
   299 	{
   300 	_asm push ebx
   301 	_asm push edi
   302 	_asm mov edi, [esp+12]
   303 	_asm mov ebx, [esp+16]
   304 	_asm mov ecx, [esp+20]
   305 	_asm mov eax, [edi]
   306 	_asm mov edx, [edi+4]
   307 	_asm retry:
   308 	_asm __LOCK__ cmpxchg8b [edi]
   309 	_asm jne short retry
   310 	_asm mov eax, ebx
   311 	_asm mov edx, ecx
   312 	_asm pop edi
   313 	_asm pop ebx
   314 	_asm ret
   315 	}
   316 
   317 
   318 /** Write a 64 bit word with full barrier semantics
   319 
   320 	@param	a	Address of word to be written - must be a multiple of 8
   321 	@param	v	The value to be written
   322 	@return		The value written
   323 */
   324 EXPORT_C __NAKED__ TUint64	__e32_atomic_store_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
   325 	{
   326 	_asm jmp __e32_atomic_store_rel64
   327 	}
   328 
   329 
   330 /** Write a 64 bit word to memory and return the original value of the memory.
   331 	Relaxed ordering.
   332 
   333 	@param	a	Address of word to be written - must be a multiple of 8
   334 	@param	v	The value to be written
   335 	@return		The original value of *a
   336 */
   337 EXPORT_C __NAKED__ TUint64	__e32_atomic_swp_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
   338 	{
   339 	_asm jmp __e32_atomic_swp_ord64
   340 	}
   341 
   342 
   343 /** Write a 64 bit word to memory and return the original value of the memory.
   344 	Acquire semantics.
   345 
   346 	@param	a	Address of word to be written - must be a multiple of 8
   347 	@param	v	The value to be written
   348 	@return		The original value of *a
   349 */
   350 EXPORT_C __NAKED__ TUint64	__e32_atomic_swp_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
   351 	{
   352 	_asm jmp __e32_atomic_swp_ord64
   353 	}
   354 
   355 
   356 /** Write a 64 bit word to memory and return the original value of the memory.
   357 	Release semantics.
   358 
   359 	@param	a	Address of word to be written - must be a multiple of 8
   360 	@param	v	The value to be written
   361 	@return		The original value of *a
   362 */
   363 EXPORT_C __NAKED__ TUint64	__e32_atomic_swp_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
   364 	{
   365 	_asm jmp __e32_atomic_swp_ord64
   366 	}
   367 
   368 
   369 /** Write a 64 bit word to memory and return the original value of the memory.
   370 	Full barrier semantics.
   371 
   372 	@param	a	Address of word to be written - must be a multiple of 8
   373 	@param	v	The value to be written
   374 	@return		The original value of *a
   375 */
   376 EXPORT_C __NAKED__ TUint64	__e32_atomic_swp_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
   377 	{
   378 	_asm push ebx
   379 	_asm push edi
   380 	_asm mov edi, [esp+12]
   381 	_asm mov ebx, [esp+16]
   382 	_asm mov ecx, [esp+20]
   383 	_asm mov eax, [edi]
   384 	_asm mov edx, [edi+4]
   385 	_asm retry:
   386 	_asm __LOCK__ cmpxchg8b [edi]
   387 	_asm jne short retry
   388 	_asm pop edi
   389 	_asm pop ebx
   390 	_asm ret
   391 	}
   392 
   393 
   394 /** 64 bit compare and swap, relaxed ordering.
   395 
   396 	Atomically performs the following operation:
   397 		if (*a == *q)	{ *a = v; return TRUE; }
   398 		else			{ *q = *a; return FALSE; }
   399 
   400 	@param	a	Address of word to be written - must be a multiple of 8
   401 	@param	q	Address of location containing expected value
   402 	@param	v	The new value to be written if the old value is as expected
   403 	@return		TRUE if *a was updated, FALSE otherwise
   404 */
   405 EXPORT_C __NAKED__ TBool		__e32_atomic_cas_rlx64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
   406 	{
   407 	_asm jmp __e32_atomic_cas_ord64
   408 	}
   409 
   410 
   411 /** 64 bit compare and swap, acquire semantics.
   412 
   413 	Atomically performs the following operation:
   414 		if (*a == *q)	{ *a = v; return TRUE; }
   415 		else			{ *q = *a; return FALSE; }
   416 
   417 	@param	a	Address of word to be written - must be a multiple of 8
   418 	@param	q	Address of location containing expected value
   419 	@param	v	The new value to be written if the old value is as expected
   420 	@return		TRUE if *a was updated, FALSE otherwise
   421 */
   422 EXPORT_C __NAKED__ TBool		__e32_atomic_cas_acq64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
   423 	{
   424 	_asm jmp __e32_atomic_cas_ord64
   425 	}
   426 
   427 
   428 /** 64 bit compare and swap, release semantics.
   429 
   430 	Atomically performs the following operation:
   431 		if (*a == *q)	{ *a = v; return TRUE; }
   432 		else			{ *q = *a; return FALSE; }
   433 
   434 	@param	a	Address of word to be written - must be a multiple of 8
   435 	@param	q	Address of location containing expected value
   436 	@param	v	The new value to be written if the old value is as expected
   437 	@return		TRUE if *a was updated, FALSE otherwise
   438 */
   439 EXPORT_C __NAKED__ TBool		__e32_atomic_cas_rel64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
   440 	{
   441 	_asm jmp __e32_atomic_cas_ord64
   442 	}
   443 
   444 
   445 /** 64 bit compare and swap, full barrier semantics.
   446 
   447 	Atomically performs the following operation:
   448 		if (*a == *q)	{ *a = v; return TRUE; }
   449 		else			{ *q = *a; return FALSE; }
   450 
   451 	@param	a	Address of word to be written - must be a multiple of 8
   452 	@param	q	Address of location containing expected value
   453 	@param	v	The new value to be written if the old value is as expected
   454 	@return		TRUE if *a was updated, FALSE otherwise
   455 */
   456 EXPORT_C __NAKED__ TBool		__e32_atomic_cas_ord64(volatile TAny* /*a*/, TUint64* /*q*/, TUint64 /*v*/)
   457 	{
   458 	_asm push ebx
   459 	_asm push edi
   460 	_asm push esi
   461 	_asm mov edi, [esp+16]				// edi = a
   462 	_asm mov esi, [esp+20]				// esi = q
   463 	_asm mov ebx, [esp+24]				// ecx:ebx = v
   464 	_asm mov ecx, [esp+28]
   465 	_asm mov eax, [esi]					// edx:eax = *q
   466 	_asm mov edx, [esi+4]
   467 	_asm __LOCK__ cmpxchg8b [edi]		// if (*a==*q) *a=v, ZF=1 else edx:eax=*a, ZF=0
   468 	_asm jne short cas_fail
   469 	_asm mov eax, 1
   470 	_asm pop esi
   471 	_asm pop edi
   472 	_asm pop ebx
   473 	_asm ret
   474 	_asm cas_fail:
   475 	_asm mov [esi], eax					// *q = edx:eax
   476 	_asm mov [esi+4], edx
   477 	_asm xor eax, eax
   478 	_asm pop esi
   479 	_asm pop edi
   480 	_asm pop ebx
   481 	_asm ret
   482 	}
   483 
   484 
   485 /** 64 bit atomic add, relaxed ordering.
   486 
   487 	Atomically performs the following operation:
   488 		oldv = *a; *a = oldv + v; return oldv;
   489 
   490 	@param	a	Address of word to be updated - must be a multiple of 8
   491 	@param	v	The value to be added
   492 	@return		The original value of *a
   493 */
   494 EXPORT_C __NAKED__ TUint64	__e32_atomic_add_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
   495 	{
   496 	_asm jmp __e32_atomic_add_ord64
   497 	}
   498 
   499 
   500 /** 64 bit atomic add, acquire semantics.
   501 
   502 	Atomically performs the following operation:
   503 		oldv = *a; *a = oldv + v; return oldv;
   504 
   505 	@param	a	Address of word to be updated - must be a multiple of 8
   506 	@param	v	The value to be added
   507 	@return		The original value of *a
   508 */
   509 EXPORT_C __NAKED__ TUint64	__e32_atomic_add_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
   510 	{
   511 	_asm jmp __e32_atomic_add_ord64
   512 	}
   513 
   514 
   515 /** 64 bit atomic add, release semantics.
   516 
   517 	Atomically performs the following operation:
   518 		oldv = *a; *a = oldv + v; return oldv;
   519 
   520 	@param	a	Address of word to be updated - must be a multiple of 8
   521 	@param	v	The value to be added
   522 	@return		The original value of *a
   523 */
   524 EXPORT_C __NAKED__ TUint64	__e32_atomic_add_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
   525 	{
   526 	_asm jmp __e32_atomic_add_ord64
   527 	}
   528 
   529 
   530 /** 64 bit atomic add, full barrier semantics.
   531 
   532 	Atomically performs the following operation:
   533 		oldv = *a; *a = oldv + v; return oldv;
   534 
   535 	@param	a	Address of word to be updated - must be a multiple of 8
   536 	@param	v	The value to be added
   537 	@return		The original value of *a
   538 */
   539 EXPORT_C __NAKED__ TUint64	__e32_atomic_add_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
   540 	{
   541 	_asm push ebx
   542 	_asm push edi
   543 	_asm mov edi, [esp+12]				// edi = a
   544 	_asm mov eax, [edi]					// edx:eax = oldv
   545 	_asm mov edx, [edi+4]
   546 	_asm retry:
   547 	_asm mov ebx, eax
   548 	_asm mov ecx, edx
   549 	_asm add ebx, [esp+16]				// ecx:ebx = oldv + v
   550 	_asm adc ecx, [esp+20]
   551 	_asm __LOCK__ cmpxchg8b [edi]		// if (*a==oldv) *a=oldv+v, ZF=1 else edx:eax=*a, ZF=0
   552 	_asm jne short retry
   553 	_asm pop edi
   554 	_asm pop ebx
   555 	_asm ret
   556 	}
   557 
   558 
   559 /** 64 bit atomic bitwise logical AND, relaxed ordering.
   560 
   561 	Atomically performs the following operation:
   562 		oldv = *a; *a = oldv & v; return oldv;
   563 
   564 	@param	a	Address of word to be updated - must be a multiple of 8
   565 	@param	v	The value to be ANDed with *a
   566 	@return		The original value of *a
   567 */
   568 EXPORT_C __NAKED__ TUint64	__e32_atomic_and_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
   569 	{
   570 	_asm jmp __e32_atomic_and_ord64
   571 	}
   572 
   573 
   574 /** 64 bit atomic bitwise logical AND, acquire semantics.
   575 
   576 	Atomically performs the following operation:
   577 		oldv = *a; *a = oldv & v; return oldv;
   578 
   579 	@param	a	Address of word to be updated - must be a multiple of 8
   580 	@param	v	The value to be ANDed with *a
   581 	@return		The original value of *a
   582 */
   583 EXPORT_C __NAKED__ TUint64	__e32_atomic_and_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
   584 	{
   585 	_asm jmp __e32_atomic_and_ord64
   586 	}
   587 
   588 
   589 /** 64 bit atomic bitwise logical AND, release semantics.
   590 
   591 	Atomically performs the following operation:
   592 		oldv = *a; *a = oldv & v; return oldv;
   593 
   594 	@param	a	Address of word to be updated - must be a multiple of 8
   595 	@param	v	The value to be ANDed with *a
   596 	@return		The original value of *a
   597 */
   598 EXPORT_C __NAKED__ TUint64	__e32_atomic_and_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
   599 	{
   600 	_asm jmp __e32_atomic_and_ord64
   601 	}
   602 
   603 
   604 /** 64 bit atomic bitwise logical AND, full barrier semantics.
   605 
   606 	Atomically performs the following operation:
   607 		oldv = *a; *a = oldv & v; return oldv;
   608 
   609 	@param	a	Address of word to be updated - must be a multiple of 8
   610 	@param	v	The value to be ANDed with *a
   611 	@return		The original value of *a
   612 */
   613 EXPORT_C __NAKED__ TUint64	__e32_atomic_and_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
   614 	{
   615 	_asm push ebx
   616 	_asm push edi
   617 	_asm mov edi, [esp+12]				// edi = a
   618 	_asm mov eax, [edi]					// edx:eax = oldv
   619 	_asm mov edx, [edi+4]
   620 	_asm retry:
   621 	_asm mov ebx, eax
   622 	_asm mov ecx, edx
   623 	_asm and ebx, [esp+16]				// ecx:ebx = oldv & v
   624 	_asm and ecx, [esp+20]
   625 	_asm __LOCK__ cmpxchg8b [edi]		// if (*a==oldv) *a=oldv&v, ZF=1 else edx:eax=*a, ZF=0
   626 	_asm jne short retry
   627 	_asm pop edi
   628 	_asm pop ebx
   629 	_asm ret
   630 	}
   631 
   632 
   633 /** 64 bit atomic bitwise logical inclusive OR, relaxed ordering.
   634 
   635 	Atomically performs the following operation:
   636 		oldv = *a; *a = oldv | v; return oldv;
   637 
   638 	@param	a	Address of word to be updated - must be a multiple of 8
   639 	@param	v	The value to be ORed with *a
   640 	@return		The original value of *a
   641 */
   642 EXPORT_C __NAKED__ TUint64	__e32_atomic_ior_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
   643 	{
   644 	_asm jmp __e32_atomic_ior_ord64
   645 	}
   646 
   647 
   648 /** 64 bit atomic bitwise logical inclusive OR, acquire semantics.
   649 
   650 	Atomically performs the following operation:
   651 		oldv = *a; *a = oldv | v; return oldv;
   652 
   653 	@param	a	Address of word to be updated - must be a multiple of 8
   654 	@param	v	The value to be ORed with *a
   655 	@return		The original value of *a
   656 */
   657 EXPORT_C __NAKED__ TUint64	__e32_atomic_ior_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
   658 	{
   659 	_asm jmp __e32_atomic_ior_ord64
   660 	}
   661 
   662 
   663 /** 64 bit atomic bitwise logical inclusive OR, release semantics.
   664 
   665 	Atomically performs the following operation:
   666 		oldv = *a; *a = oldv | v; return oldv;
   667 
   668 	@param	a	Address of word to be updated - must be a multiple of 8
   669 	@param	v	The value to be ORed with *a
   670 	@return		The original value of *a
   671 */
   672 EXPORT_C __NAKED__ TUint64	__e32_atomic_ior_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
   673 	{
   674 	_asm jmp __e32_atomic_ior_ord64
   675 	}
   676 
   677 
   678 /** 64 bit atomic bitwise logical inclusive OR, full barrier semantics.
   679 
   680 	Atomically performs the following operation:
   681 		oldv = *a; *a = oldv | v; return oldv;
   682 
   683 	@param	a	Address of word to be updated - must be a multiple of 8
   684 	@param	v	The value to be ORed with *a
   685 	@return		The original value of *a
   686 */
   687 EXPORT_C __NAKED__ TUint64	__e32_atomic_ior_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
   688 	{
   689 	_asm push ebx
   690 	_asm push edi
   691 	_asm mov edi, [esp+12]				// edi = a
   692 	_asm mov eax, [edi]					// edx:eax = oldv
   693 	_asm mov edx, [edi+4]
   694 	_asm retry:
   695 	_asm mov ebx, eax
   696 	_asm mov ecx, edx
   697 	_asm or ebx, [esp+16]				// ecx:ebx = oldv | v
   698 	_asm or ecx, [esp+20]
   699 	_asm __LOCK__ cmpxchg8b [edi]		// if (*a==oldv) *a=oldv|v, ZF=1 else edx:eax=*a, ZF=0
   700 	_asm jne short retry
   701 	_asm pop edi
   702 	_asm pop ebx
   703 	_asm ret
   704 	}
   705 
   706 
   707 /** 64 bit atomic bitwise logical exclusive OR, relaxed ordering.
   708 
   709 	Atomically performs the following operation:
   710 		oldv = *a; *a = oldv ^ v; return oldv;
   711 
   712 	@param	a	Address of word to be updated - must be a multiple of 8
   713 	@param	v	The value to be XORed with *a
   714 	@return		The original value of *a
   715 */
   716 EXPORT_C __NAKED__ TUint64	__e32_atomic_xor_rlx64(volatile TAny* /*a*/, TUint64 /*v*/)
   717 	{
   718 	_asm jmp __e32_atomic_xor_ord64
   719 	}
   720 
   721 
   722 /** 64 bit atomic bitwise logical exclusive OR, acquire semantics.
   723 
   724 	Atomically performs the following operation:
   725 		oldv = *a; *a = oldv ^ v; return oldv;
   726 
   727 	@param	a	Address of word to be updated - must be a multiple of 8
   728 	@param	v	The value to be XORed with *a
   729 	@return		The original value of *a
   730 */
   731 EXPORT_C __NAKED__ TUint64	__e32_atomic_xor_acq64(volatile TAny* /*a*/, TUint64 /*v*/)
   732 	{
   733 	_asm jmp __e32_atomic_xor_ord64
   734 	}
   735 
   736 
   737 /** 64 bit atomic bitwise logical exclusive OR, release semantics.
   738 
   739 	Atomically performs the following operation:
   740 		oldv = *a; *a = oldv ^ v; return oldv;
   741 
   742 	@param	a	Address of word to be updated - must be a multiple of 8
   743 	@param	v	The value to be XORed with *a
   744 	@return		The original value of *a
   745 */
   746 EXPORT_C __NAKED__ TUint64	__e32_atomic_xor_rel64(volatile TAny* /*a*/, TUint64 /*v*/)
   747 	{
   748 	_asm jmp __e32_atomic_xor_ord64
   749 	}
   750 
   751 
   752 /** 64 bit atomic bitwise logical exclusive OR, full barrier semantics.
   753 
   754 	Atomically performs the following operation:
   755 		oldv = *a; *a = oldv ^ v; return oldv;
   756 
   757 	@param	a	Address of word to be updated - must be a multiple of 8
   758 	@param	v	The value to be XORed with *a
   759 	@return		The original value of *a
   760 */
   761 EXPORT_C __NAKED__ TUint64	__e32_atomic_xor_ord64(volatile TAny* /*a*/, TUint64 /*v*/)
   762 	{
   763 	_asm push ebx
   764 	_asm push edi
   765 	_asm mov edi, [esp+12]				// edi = a
   766 	_asm mov eax, [edi]					// edx:eax = oldv
   767 	_asm mov edx, [edi+4]
   768 	_asm retry:
   769 	_asm mov ebx, eax
   770 	_asm mov ecx, edx
   771 	_asm xor ebx, [esp+16]				// ecx:ebx = oldv ^ v
   772 	_asm xor ecx, [esp+20]
   773 	_asm __LOCK__ cmpxchg8b [edi]		// if (*a==oldv) *a=oldv^v, ZF=1 else edx:eax=*a, ZF=0
   774 	_asm jne short retry
   775 	_asm pop edi
   776 	_asm pop ebx
   777 	_asm ret
   778 	}
   779 
   780 
   781 /** 64 bit atomic bitwise universal function, relaxed ordering.
   782 
   783 	Atomically performs the following operation:
   784 		oldv = *a; *a = (oldv & u) ^ v; return oldv;
   785 
   786 	@param	a	Address of word to be updated - must be a multiple of 8
   787 	@param	u	The value to be ANDed with *a
   788 	@param	v	The value to be XORed with (*a&u)
   789 	@return		The original value of *a
   790 */
   791 EXPORT_C __NAKED__ TUint64	__e32_atomic_axo_rlx64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
   792 	{
   793 	_asm jmp __e32_atomic_axo_ord64
   794 	}
   795 
   796 
   797 /** 64 bit atomic bitwise universal function, acquire semantics.
   798 
   799 	Atomically performs the following operation:
   800 		oldv = *a; *a = (oldv & u) ^ v; return oldv;
   801 
   802 	@param	a	Address of word to be updated - must be a multiple of 8
   803 	@param	u	The value to be ANDed with *a
   804 	@param	v	The value to be XORed with (*a&u)
   805 	@return		The original value of *a
   806 */
   807 EXPORT_C __NAKED__ TUint64	__e32_atomic_axo_acq64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
   808 	{
   809 	_asm jmp __e32_atomic_axo_ord64
   810 	}
   811 
   812 
   813 /** 64 bit atomic bitwise universal function, release semantics.
   814 
   815 	Atomically performs the following operation:
   816 		oldv = *a; *a = (oldv & u) ^ v; return oldv;
   817 
   818 	@param	a	Address of word to be updated - must be a multiple of 8
   819 	@param	u	The value to be ANDed with *a
   820 	@param	v	The value to be XORed with (*a&u)
   821 	@return		The original value of *a
   822 */
   823 EXPORT_C __NAKED__ TUint64	__e32_atomic_axo_rel64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
   824 	{
   825 	_asm jmp __e32_atomic_axo_ord64
   826 	}
   827 
   828 
   829 /** 64 bit atomic bitwise universal function, release semantics.
   830 
   831 	Atomically performs the following operation:
   832 		oldv = *a; *a = (oldv & u) ^ v; return oldv;
   833 
   834 	@param	a	Address of word to be updated - must be a multiple of 8
   835 	@param	u	The value to be ANDed with *a
   836 	@param	v	The value to be XORed with (*a&u)
   837 	@return		The original value of *a
   838 */
   839 EXPORT_C __NAKED__ TUint64	__e32_atomic_axo_ord64(volatile TAny* /*a*/, TUint64 /*u*/, TUint64 /*v*/)
   840 	{
   841 	_asm push ebx
   842 	_asm push edi
   843 	_asm mov edi, [esp+12]				// edi = a
   844 	_asm mov eax, [edi]					// edx:eax = oldv
   845 	_asm mov edx, [edi+4]
   846 	_asm retry:
   847 	_asm mov ebx, eax
   848 	_asm mov ecx, edx
   849 	_asm and ebx, [esp+16]				// ecx:ebx = oldv & u
   850 	_asm and ecx, [esp+20]
   851 	_asm xor ebx, [esp+24]				// ecx:ebx = (oldv & u) ^ v
   852 	_asm xor ecx, [esp+28]
   853 	_asm __LOCK__ cmpxchg8b [edi]		// if (*a==oldv) *a=(oldv&u)^v, ZF=1 else edx:eax=*a, ZF=0
   854 	_asm jne short retry
   855 	_asm pop edi
   856 	_asm pop ebx
   857 	_asm ret
   858 	}
   859 
   860 
   861 /** 64 bit threshold and add, unsigned, relaxed ordering.
   862 
   863 	Atomically performs the following operation:
   864 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
   865 
   866 	@param	a	Address of data to be updated - must be naturally aligned
   867 	@param	t	The threshold to compare *a to (unsigned compare)
   868 	@param	u	The value to be added to *a if it is originally >= t
   869 	@param	u	The value to be added to *a if it is originally < t
   870 	@return		The original value of *a
   871 */
   872 EXPORT_C __NAKED__ TUint64	__e32_atomic_tau_rlx64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
   873 	{
   874 	_asm jmp __e32_atomic_tau_ord64
   875 	}
   876 
   877 
   878 /** 64 bit threshold and add, unsigned, acquire semantics.
   879 
   880 	Atomically performs the following operation:
   881 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
   882 
   883 	@param	a	Address of data to be updated - must be naturally aligned
   884 	@param	t	The threshold to compare *a to (unsigned compare)
   885 	@param	u	The value to be added to *a if it is originally >= t
   886 	@param	u	The value to be added to *a if it is originally < t
   887 	@return		The original value of *a
   888 */
   889 EXPORT_C __NAKED__ TUint64	__e32_atomic_tau_acq64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
   890 	{
   891 	_asm jmp __e32_atomic_tau_ord64
   892 	}
   893 
   894 
   895 /** 64 bit threshold and add, unsigned, release semantics.
   896 
   897 	Atomically performs the following operation:
   898 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
   899 
   900 	@param	a	Address of data to be updated - must be naturally aligned
   901 	@param	t	The threshold to compare *a to (unsigned compare)
   902 	@param	u	The value to be added to *a if it is originally >= t
   903 	@param	u	The value to be added to *a if it is originally < t
   904 	@return		The original value of *a
   905 */
   906 EXPORT_C __NAKED__ TUint64	__e32_atomic_tau_rel64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
   907 	{
   908 	_asm jmp __e32_atomic_tau_ord64
   909 	}
   910 
   911 
   912 /** 64 bit threshold and add, unsigned, full barrier semantics.
   913 
   914 	Atomically performs the following operation:
   915 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
   916 
   917 	@param	a	Address of data to be updated - must be naturally aligned
   918 	@param	t	The threshold to compare *a to (unsigned compare)
   919 	@param	u	The value to be added to *a if it is originally >= t
   920 	@param	u	The value to be added to *a if it is originally < t
   921 	@return		The original value of *a
   922 */
   923 EXPORT_C __NAKED__ TUint64	__e32_atomic_tau_ord64(volatile TAny* /*a*/, TUint64 /*t*/, TUint64 /*u*/, TUint64 /*v*/)
   924 	{
   925 	_asm push ebx
   926 	_asm push edi
   927 	_asm mov edi, [esp+12]				// edi = a
   928 	_asm mov eax, [edi]					// edx:eax = oldv
   929 	_asm mov edx, [edi+4]
   930 	_asm retry:
   931 	_asm mov ebx, edx
   932 	_asm cmp eax, [esp+16]				// eax - t.low, CF=borrow
   933 	_asm sbb ebx, [esp+20]				// CF = borrow from (oldv - t)
   934 	_asm jnc short use_u				// no borrow means oldv>=t so use u
   935 	_asm mov ebx, [esp+32]				// ecx:ebx = v
   936 	_asm mov ecx, [esp+36]
   937 	_asm jmp short use_v
   938 	_asm use_u:
   939 	_asm mov ebx, [esp+24]				// ecx:ebx = u
   940 	_asm mov ecx, [esp+28]
   941 	_asm use_v:
   942 	_asm add ebx, eax					// ecx:ebx = oldv + u or v
   943 	_asm adc ecx, edx
   944 	_asm __LOCK__ cmpxchg8b [edi]
   945 	_asm jne short retry
   946 	_asm pop edi
   947 	_asm pop ebx
   948 	_asm ret
   949 	}
   950 
   951 
   952 /** 64 bit threshold and add, signed, relaxed ordering.
   953 
   954 	Atomically performs the following operation:
   955 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
   956 
   957 	@param	a	Address of data to be updated - must be naturally aligned
   958 	@param	t	The threshold to compare *a to (signed compare)
   959 	@param	u	The value to be added to *a if it is originally >= t
   960 	@param	u	The value to be added to *a if it is originally < t
   961 	@return		The original value of *a
   962 */
   963 EXPORT_C __NAKED__ TInt64	__e32_atomic_tas_rlx64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
   964 	{
   965 	_asm jmp __e32_atomic_tas_ord64
   966 	}
   967 
   968 
   969 /** 64 bit threshold and add, signed, acquire semantics.
   970 
   971 	Atomically performs the following operation:
   972 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
   973 
   974 	@param	a	Address of data to be updated - must be naturally aligned
   975 	@param	t	The threshold to compare *a to (signed compare)
   976 	@param	u	The value to be added to *a if it is originally >= t
   977 	@param	u	The value to be added to *a if it is originally < t
   978 	@return		The original value of *a
   979 */
   980 EXPORT_C __NAKED__ TInt64	__e32_atomic_tas_acq64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
   981 	{
   982 	_asm jmp __e32_atomic_tas_ord64
   983 	}
   984 
   985 
   986 /** 64 bit threshold and add, signed, release semantics.
   987 
   988 	Atomically performs the following operation:
   989 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
   990 
   991 	@param	a	Address of data to be updated - must be naturally aligned
   992 	@param	t	The threshold to compare *a to (signed compare)
   993 	@param	u	The value to be added to *a if it is originally >= t
   994 	@param	u	The value to be added to *a if it is originally < t
   995 	@return		The original value of *a
   996 */
   997 EXPORT_C __NAKED__ TInt64	__e32_atomic_tas_rel64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
   998 	{
   999 	_asm jmp __e32_atomic_tas_ord64
  1000 	}
  1001 
  1002 
  1003 /** 64 bit threshold and add, signed, full barrier semantics.
  1004 
  1005 	Atomically performs the following operation:
  1006 		oldv = *a; if (oldv>=t) *a=oldv+u else *a=oldv+v; return oldv;
  1007 
  1008 	@param	a	Address of data to be updated - must be naturally aligned
  1009 	@param	t	The threshold to compare *a to (signed compare)
  1010 	@param	u	The value to be added to *a if it is originally >= t
  1011 	@param	u	The value to be added to *a if it is originally < t
  1012 	@return		The original value of *a
  1013 */
  1014 EXPORT_C __NAKED__ TInt64	__e32_atomic_tas_ord64(volatile TAny* /*a*/, TInt64 /*t*/, TInt64 /*u*/, TInt64 /*v*/)
  1015 	{
  1016 	_asm push ebx
  1017 	_asm push edi
  1018 	_asm mov edi, [esp+12]				// edi = a
  1019 	_asm mov eax, [edi]					// edx:eax = oldv
  1020 	_asm mov edx, [edi+4]
  1021 	_asm retry:
  1022 	_asm mov ebx, edx
  1023 	_asm cmp eax, [esp+16]				// eax - t.low, CF=borrow
  1024 	_asm sbb ebx, [esp+20]				// SF=sign, OF=overflow from (oldv - t)
  1025 	_asm jge short use_u				// SF==OF (GE condition) means oldv>=t so use u
  1026 	_asm mov ebx, [esp+32]				// ecx:ebx = v
  1027 	_asm mov ecx, [esp+36]
  1028 	_asm jmp short use_v
  1029 	_asm use_u:
  1030 	_asm mov ebx, [esp+24]				// ecx:ebx = u
  1031 	_asm mov ecx, [esp+28]
  1032 	_asm use_v:
  1033 	_asm add ebx, eax					// ecx:ebx = oldv + u or v
  1034 	_asm adc ecx, edx
  1035 	_asm __LOCK__ cmpxchg8b [edi]
  1036 	_asm jne short retry
  1037 	_asm pop edi
  1038 	_asm pop ebx
  1039 	_asm ret
  1040 	}
  1041 
  1042 } // extern "C"