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