kerneltest/e32test/system/t_atomic.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32test\system\t_atomic.cpp
// 
//

#define	__E32TEST_EXTENSION__

#include <e32test.h>
#include <e32atomics.h>
#include <u32hal.h>
#include "u32std.h"
#include <e32svr.h>
#include <hal.h>

RTest test(_L("T_ATOMIC"));

#include "t_atomic.h"

#ifdef __EPOC32__
RTestAtomic	DD;
#endif

extern "C" {
extern const char* FuncName[];
extern const PFV AtomicFuncPtr[];
extern const PFV ControlFuncPtr[];
extern const TUint FuncAttr[];
}

class TestOverflowTruncate2 : public TDes16Overflow
	{
public:
	virtual void Overflow(TDes16 &aDes);
	};

void TestOverflowTruncate2::Overflow(TDes16& /*aDes*/)
	{
	}

void UPrintf(const char* aFmt, ...)
	{
	// Print to a console screen.
	TestOverflowTruncate2 overflow;
	VA_LIST list;
	VA_START(list, aFmt);
	TBuf8<256> fmtBuf8((const TUint8*)aFmt);
	TBuf<256> buf;
	buf.AppendFormatList(fmtBuf8.Expand(), list, &overflow);
	test.Printf(_L("%S\n"),&buf);
	}

/******************************************************************************
 * Single thread normal operation tests
 ******************************************************************************/
template<class T>
struct TD
	{
	T		i0;
	T		i1;
	T		i2;
	T		i3;
	TInt	iF;
	TInt	iPadding;
	};

struct TDG : public TDGBase
	{
	void Set(const TD<TUint8>	aTD8,	TInt aOrd);
	void Set(const TD<TUint16>	aTD16,	TInt aOrd);
	void Set(const TD<TUint32>	aTD32,	TInt aOrd);
	void Set(const TD<TUint64>	aTD64,	TInt aOrd);

	TInt ExecuteUser();
	TInt ExecuteKernel();
	};

TInt GetAtomicFuncIndex(TInt aFunc, TInt aSize, TInt aOrd)
	{
	test_NotNegative(aFunc);
	test_Compare(aFunc,<,EAtomicFuncN);
	test_NotNegative(aOrd);
	test_Compare(aOrd,<,4);
	aFunc *= 4;
	switch(aSize)
		{
		case 1:	break;
		case 2:	aFunc += INDEXES_PER_SIZE; break;
		case 4:	aFunc += 2*INDEXES_PER_SIZE; break;
		case 8:	aFunc += 3*INDEXES_PER_SIZE; break;
		default: test_Equal(8,aSize); break;
		}
	aFunc += aOrd;
	if (AtomicFuncPtr[aFunc])
		return aFunc;
	return -1;
	}

void TDG::Set(const TD<TUint8> aTD8, TInt aOrd)
	{
	i0 = aTD8.i0;
	i1 = aTD8.i1;
	i2 = aTD8.i2;
	i3 = aTD8.i3;
	iIndex = GetAtomicFuncIndex(aTD8.iF, 1, aOrd);
#ifdef __EXTRA_DEBUG__
	DEBUGPRINT(" 8: iF=%2d aOrd=%1d -> %d", aTD8.iF, aOrd, iIndex);
#endif
	}

void TDG::Set(const TD<TUint16> aTD16, TInt aOrd)
	{
	i0 = aTD16.i0;
	i1 = aTD16.i1;
	i2 = aTD16.i2;
	i3 = aTD16.i3;
	iIndex = GetAtomicFuncIndex(aTD16.iF, 2, aOrd);
#ifdef __EXTRA_DEBUG__
	DEBUGPRINT("16: iF=%2d aOrd=%1d -> %d", aTD16.iF, aOrd, iIndex);
#endif
	}

void TDG::Set(const TD<TUint32> aTD32, TInt aOrd)
	{
	i0 = aTD32.i0;
	i1 = aTD32.i1;
	i2 = aTD32.i2;
	i3 = aTD32.i3;
	iIndex = GetAtomicFuncIndex(aTD32.iF, 4, aOrd);
#ifdef __EXTRA_DEBUG__
	DEBUGPRINT("32: iF=%2d aOrd=%1d -> %d", aTD32.iF, aOrd, iIndex);
#endif
	}

void TDG::Set(const TD<TUint64> aTD64, TInt aOrd)
	{
	i0 = aTD64.i0;
	i1 = aTD64.i1;
	i2 = aTD64.i2;
	i3 = aTD64.i3;
	iIndex = GetAtomicFuncIndex(aTD64.iF, 8, aOrd);
#ifdef __EXTRA_DEBUG__
	DEBUGPRINT("64: iF=%2d aOrd=%1d -> %d", aTD64.iF, aOrd, iIndex);
#endif
	}

TInt TDG::ExecuteUser()
	{
	return Execute();
	}

#ifdef __EPOC32__
TInt TDG::ExecuteKernel()
	{
	return DD.TDGExecuteK(*this);
	}
#endif


#define	DCL_TEST_BLOCK(type,name)			\
	static const TD<type> name[] =
#define	DCL_TEST1(type,func,a0)				\
	{	(type)(a0),	(type)(0),	(type)(0),	(type)(0),	(EAtomicFunc##func),	0	}
#define	DCL_TEST2(type,func,a0,a1)			\
	{	(type)(a0),	(type)(a1),	(type)(0),	(type)(0),	(EAtomicFunc##func),	0	}
#define	DCL_TEST3(type,func,a0,a1,a2)		\
	{	(type)(a0),	(type)(a1),	(type)(a2),	(type)(0),	(EAtomicFunc##func),	0	}
#define	DCL_TEST4(type,func,a0,a1,a2,a3)	\
	{	(type)(a0),	(type)(a1),	(type)(a2),	(type)(a3),	(EAtomicFunc##func),	0	}

DCL_TEST_BLOCK(TUint8,TestData8)
	{
	DCL_TEST1(TUint8,	LOAD,	0x00),
	DCL_TEST1(TUint8,	LOAD,	0xFF),

	DCL_TEST2(TUint8,	STORE,	0xBB, 0x00),
	DCL_TEST2(TUint8,	STORE,	0xBB, 0xFF),

	DCL_TEST2(TUint8,	SWP,	0xBB, 0x00),
	DCL_TEST2(TUint8,	SWP,	0xBB, 0xFF),
	DCL_TEST2(TUint8,	SWP,	0x55, 0x00),
	DCL_TEST2(TUint8,	SWP,	0x55, 0xFF),

	DCL_TEST2(TUint8,	ADD,	0x00, 0x01),
	DCL_TEST2(TUint8,	ADD,	0xFF, 0x01),
	DCL_TEST2(TUint8,	ADD,	0xFE, 0x01),
	DCL_TEST2(TUint8,	ADD,	0xFE, 0x02),
	DCL_TEST2(TUint8,	ADD,	0xFE, 0x03),
	DCL_TEST2(TUint8,	ADD,	0x12, 0x23),

	DCL_TEST2(TUint8,	AND,	0x00, 0x01),
	DCL_TEST2(TUint8,	AND,	0xFF, 0x01),
	DCL_TEST2(TUint8,	AND,	0xFE, 0x01),
	DCL_TEST2(TUint8,	AND,	0xFE, 0xFF),
	DCL_TEST2(TUint8,	AND,	0xFE, 0x03),
	DCL_TEST2(TUint8,	AND,	0x5F, 0xAF),

	DCL_TEST2(TUint8,	IOR,	0x00, 0x01),
	DCL_TEST2(TUint8,	IOR,	0xFF, 0x01),
	DCL_TEST2(TUint8,	IOR,	0xFE, 0x01),
	DCL_TEST2(TUint8,	IOR,	0x0D, 0x5F),
	DCL_TEST2(TUint8,	IOR,	0x30, 0x03),
	DCL_TEST2(TUint8,	IOR,	0x5F, 0xAF),

	DCL_TEST2(TUint8,	XOR,	0x00, 0x01),
	DCL_TEST2(TUint8,	XOR,	0xFF, 0x01),
	DCL_TEST2(TUint8,	XOR,	0xFE, 0x01),
	DCL_TEST2(TUint8,	XOR,	0xFE, 0xFF),
	DCL_TEST2(TUint8,	XOR,	0xFE, 0x03),
	DCL_TEST2(TUint8,	XOR,	0x5F, 0xAF),

	DCL_TEST3(TUint8,	AXO,	0x00, 0xFF,	0x00),
	DCL_TEST3(TUint8,	AXO,	0x00, 0xFF,	0x33),
	DCL_TEST3(TUint8,	AXO,	0x00, 0xFF,	0x7D),
	DCL_TEST3(TUint8,	AXO,	0x00, 0xFF,	0xBB),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0x00,	0x00),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0x00,	0x33),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0x00,	0x7D),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0x00,	0xBB),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0x33,	0xF0),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0x33,	0x0F),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0xCC,	0xF0),
	DCL_TEST3(TUint8,	AXO,	0xAA, 0xCC,	0x0F),

	DCL_TEST3(TUint8,	CAS,	0x00, 0xFF,	0xEE),
	DCL_TEST3(TUint8,	CAS,	0x00, 0x01,	0x11),
	DCL_TEST3(TUint8,	CAS,	0x00, 0x00,	0xEE),
	DCL_TEST3(TUint8,	CAS,	0x00, 0x00,	0x23),
	DCL_TEST3(TUint8,	CAS,	0x2A, 0xFF,	0x2B),
	DCL_TEST3(TUint8,	CAS,	0x2A, 0x01,	0x2B),
	DCL_TEST3(TUint8,	CAS,	0x2A, 0x2A,	0x2B),
	DCL_TEST3(TUint8,	CAS,	0x2A, 0x2A,	0x3B),

	DCL_TEST4(TUint8,	TAU,	0x00, 0x00,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAU,	0x01, 0x00,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAU,	0xFF, 0x00,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAU,	0x00, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAU,	0x01, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAU,	0x02, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAU,	0xFF, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAU,	0xFE, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAU,	0xEE, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAU,	0xFF, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAU,	0x00, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAU,	0xFE, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAU,	0xEE, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAU,	0xFF, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAU,	0x00, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAU,	0xFE, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x7F, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x80, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x81, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x00, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x7E, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x7F, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x80, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x81, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAU,	0x00, 0x7F,	0x81, 0x7E),

	DCL_TEST4(TUint8,	TAS,	0x00, 0x00,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAS,	0x01, 0x00,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAS,	0xFF, 0x00,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAS,	0x00, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAS,	0x01, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAS,	0x02, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAS,	0xFF, 0x01,	0x02, 0x03),
	DCL_TEST4(TUint8,	TAS,	0xFE, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAS,	0xEE, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAS,	0xFF, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAS,	0x00, 0xFE,	0x23, 0x0B),
	DCL_TEST4(TUint8,	TAS,	0xFE, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAS,	0xEE, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAS,	0xFF, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAS,	0x00, 0xFE,	0x80, 0x7F),
	DCL_TEST4(TUint8,	TAS,	0xFE, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x7F, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x80, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x81, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x00, 0x80,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x7E, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x7F, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x80, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x81, 0x7F,	0x81, 0x7E),
	DCL_TEST4(TUint8,	TAS,	0x00, 0x7F,	0x81, 0x7E)
	};

DCL_TEST_BLOCK(TUint16,TestData16)
	{
	DCL_TEST1(TUint16,	LOAD,	0x0055),
	DCL_TEST1(TUint16,	LOAD,	0xFFAA),

	DCL_TEST2(TUint16,	STORE,	0xBBBB, 0x0055),
	DCL_TEST2(TUint16,	STORE,	0xBBBB, 0xFFAA),

	DCL_TEST2(TUint16,	SWP,	0xBBCC, 0x0055),
	DCL_TEST2(TUint16,	SWP,	0xBBCC, 0xFFAA),
	DCL_TEST2(TUint16,	SWP,	0x55AA, 0x0033),
	DCL_TEST2(TUint16,	SWP,	0x55AA, 0xFFCC),

	DCL_TEST2(TUint16,	ADD,	0x0000, 0x0001),
	DCL_TEST2(TUint16,	ADD,	0xFFFF, 0x0001),
	DCL_TEST2(TUint16,	ADD,	0xFFFE, 0x0001),
	DCL_TEST2(TUint16,	ADD,	0xFFFE, 0x0002),
	DCL_TEST2(TUint16,	ADD,	0xFFFE, 0x0003),
	DCL_TEST2(TUint16,	ADD,	0x0012, 0x0023),
	DCL_TEST2(TUint16,	ADD,	0x0012, 0xBCFF),

	DCL_TEST2(TUint16,	AND,	0x0000, 0x0001),
	DCL_TEST2(TUint16,	AND,	0xFFFF, 0x0001),
	DCL_TEST2(TUint16,	AND,	0xFFFE, 0x0001),
	DCL_TEST2(TUint16,	AND,	0xFFFE, 0xFFFF),
	DCL_TEST2(TUint16,	AND,	0xFFFE, 0x0F03),
	DCL_TEST2(TUint16,	AND,	0xBC5F, 0x14AF),

	DCL_TEST2(TUint16,	IOR,	0x0000, 0x0001),
	DCL_TEST2(TUint16,	IOR,	0xFFFF, 0x0001),
	DCL_TEST2(TUint16,	IOR,	0xFFFE, 0x0001),
	DCL_TEST2(TUint16,	IOR,	0x000D, 0x005F),
	DCL_TEST2(TUint16,	IOR,	0x8030, 0x0803),
	DCL_TEST2(TUint16,	IOR,	0x145F, 0x56AF),

	DCL_TEST2(TUint16,	XOR,	0x0000, 0x0001),
	DCL_TEST2(TUint16,	XOR,	0xFFFF, 0x0001),
	DCL_TEST2(TUint16,	XOR,	0xFFFE, 0x0001),
	DCL_TEST2(TUint16,	XOR,	0xFFFE, 0xFFFF),
	DCL_TEST2(TUint16,	XOR,	0xFFFE, 0x0003),
	DCL_TEST2(TUint16,	XOR,	0x145F, 0xBCAF),

	DCL_TEST3(TUint16,	AXO,	0x0000, 0xFFFF,	0x0000),
	DCL_TEST3(TUint16,	AXO,	0x0000, 0xFFFF,	0x6633),
	DCL_TEST3(TUint16,	AXO,	0x0000, 0xFFFF,	0x827D),
	DCL_TEST3(TUint16,	AXO,	0x0000, 0xFFFF,	0xCCBB),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0x0000,	0x0000),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0x0000,	0x6633),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0x0000,	0x827D),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0x0000,	0xCCBB),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0xCC33,	0x0FF0),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0xCC33,	0xF00F),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0x33CC,	0x0FF0),
	DCL_TEST3(TUint16,	AXO,	0xAAAA, 0x33CC,	0xF00F),

	DCL_TEST3(TUint16,	CAS,	0x0000, 0x00FF,	0x99EE),
	DCL_TEST3(TUint16,	CAS,	0x0000, 0x0001,	0x7711),
	DCL_TEST3(TUint16,	CAS,	0x0000, 0x0000,	0x99EE),
	DCL_TEST3(TUint16,	CAS,	0x0000, 0x0000,	0x1123),
	DCL_TEST3(TUint16,	CAS,	0x832A, 0xFFFF,	0x832B),
	DCL_TEST3(TUint16,	CAS,	0x832A, 0x0001,	0x832B),
	DCL_TEST3(TUint16,	CAS,	0x832A, 0x822A,	0x832B),
	DCL_TEST3(TUint16,	CAS,	0x832A, 0x832B,	0x943B),
	DCL_TEST3(TUint16,	CAS,	0x832A, 0x832A,	0x832B),
	DCL_TEST3(TUint16,	CAS,	0x832A, 0x832A,	0x943B),

	DCL_TEST4(TUint16,	TAU,	0x0000, 0x0000,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAU,	0x0001, 0x0000,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAU,	0xFFFF, 0x0000,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAU,	0x0000, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAU,	0x0001, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAU,	0x0002, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAU,	0xFFFF, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAU,	0xFFFE, 0xFFFE,	0x1023, 0x000B),
	DCL_TEST4(TUint16,	TAU,	0xFFEE, 0xFFFE,	0x1423, 0x000B),
	DCL_TEST4(TUint16,	TAU,	0xFFFF, 0xFFFE,	0x1423, 0x000B),
	DCL_TEST4(TUint16,	TAU,	0x0000, 0xFFFE,	0x1423, 0x000B),
	DCL_TEST4(TUint16,	TAU,	0xFFFE, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAU,	0xFFEE, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAU,	0xFFFF, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAU,	0x0000, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAU,	0xFFFE, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x7FFF, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x8000, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x8001, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x0000, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x7FFE, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x7FFF, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x8000, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x8001, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAU,	0x0000, 0x7FFF,	0x8001, 0x7FFE),

	DCL_TEST4(TUint16,	TAS,	0x0000, 0x0000,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAS,	0x0001, 0x0000,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAS,	0xFFFF, 0x0000,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAS,	0x0000, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAS,	0x0001, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAS,	0x0002, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAS,	0xFFFF, 0x0001,	0x0002, 0x0003),
	DCL_TEST4(TUint16,	TAS,	0xFFFE, 0xFFFE,	0x1023, 0x000B),
	DCL_TEST4(TUint16,	TAS,	0xFFEE, 0xFFFE,	0x1423, 0x000B),
	DCL_TEST4(TUint16,	TAS,	0xFFFF, 0xFFFE,	0x1423, 0x000B),
	DCL_TEST4(TUint16,	TAS,	0x0000, 0xFFFE,	0x1423, 0x000B),
	DCL_TEST4(TUint16,	TAS,	0xFFFE, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAS,	0xFFEE, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAS,	0xFFFF, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAS,	0x0000, 0xFFFE,	0x8000, 0x7FFF),
	DCL_TEST4(TUint16,	TAS,	0xFFFE, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x7FFF, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x8000, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x8001, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x0000, 0x8000,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x7FFE, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x7FFF, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x8000, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x8001, 0x7FFF,	0x8001, 0x7FFE),
	DCL_TEST4(TUint16,	TAS,	0x0000, 0x7FFF,	0x8001, 0x7FFE)
	};

DCL_TEST_BLOCK(TUint32,TestData32)
	{
	DCL_TEST1(TUint32,	LOAD,	0x00334455),
	DCL_TEST1(TUint32,	LOAD,	0xFFCCBBAA),

	DCL_TEST2(TUint32,	STORE,	0xBBBBBBBB, 0x00334455),
	DCL_TEST2(TUint32,	STORE,	0xBBBBBBBB, 0xFFCCBBAA),

	DCL_TEST2(TUint32,	SWP,	0xBB1234CC, 0x00EDCB55),
	DCL_TEST2(TUint32,	SWP,	0xBB1234CC, 0xFF9876AA),
	DCL_TEST2(TUint32,	SWP,	0x551971AA, 0x00112233),
	DCL_TEST2(TUint32,	SWP,	0x551971AA, 0xFFEEDDCC),

	DCL_TEST2(TUint32,	ADD,	0x00000000, 0x00000001),
	DCL_TEST2(TUint32,	ADD,	0xFFFFFFFF, 0x00000001),
	DCL_TEST2(TUint32,	ADD,	0xFFFFFFFE, 0x00000001),
	DCL_TEST2(TUint32,	ADD,	0xFFFFFFFE, 0x00000002),
	DCL_TEST2(TUint32,	ADD,	0xFFFFFFFE, 0x00000003),
	DCL_TEST2(TUint32,	ADD,	0x00009912, 0x00000023),
	DCL_TEST2(TUint32,	ADD,	0x00009912, 0x4937BCFF),

	DCL_TEST2(TUint32,	AND,	0x00000000, 0x00000001),
	DCL_TEST2(TUint32,	AND,	0xFFFFFFFF, 0x00000001),
	DCL_TEST2(TUint32,	AND,	0xFFFFFFFE, 0x00000001),
	DCL_TEST2(TUint32,	AND,	0xFFFFFFFE, 0xFFFFFFFF),
	DCL_TEST2(TUint32,	AND,	0xFFFFFFFE, 0x00000F03),
	DCL_TEST2(TUint32,	AND,	0xEDCBBC5F, 0xDCBA14AF),

	DCL_TEST2(TUint32,	IOR,	0x00000000, 0x00000001),
	DCL_TEST2(TUint32,	IOR,	0xFFFFFFFF, 0x00000001),
	DCL_TEST2(TUint32,	IOR,	0xFFFFFFFE, 0x00000001),
	DCL_TEST2(TUint32,	IOR,	0x0000000D, 0x0000005F),
	DCL_TEST2(TUint32,	IOR,	0x80000030, 0x00000803),
	DCL_TEST2(TUint32,	IOR,	0x89AB145F, 0x415256AF),

	DCL_TEST2(TUint32,	XOR,	0x00000000, 0x00000001),
	DCL_TEST2(TUint32,	XOR,	0xFFFFFFFF, 0x00000001),
	DCL_TEST2(TUint32,	XOR,	0xFFFFFFFE, 0x00000001),
	DCL_TEST2(TUint32,	XOR,	0xFFFFFFFE, 0xFFFFFFFF),
	DCL_TEST2(TUint32,	XOR,	0xFFFFFFFE, 0x00000003),
	DCL_TEST2(TUint32,	XOR,	0x89AB145F, 0x4152BCAF),

	DCL_TEST3(TUint32,	AXO,	0x00000000, 0xFFFFFFFF,	0x00000000),
	DCL_TEST3(TUint32,	AXO,	0x00000000, 0xFFFFFFFF,	0x99CC6633),
	DCL_TEST3(TUint32,	AXO,	0x00000000, 0xFFFFFFFF,	0x8000027D),
	DCL_TEST3(TUint32,	AXO,	0x00000000, 0xFFFFFFFF,	0xEEDDCCBB),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x00000000,	0x00000000),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x00000000,	0x99CC6633),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x00000000,	0x8000027D),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x00000000,	0xEEDDCCBB),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x9966CC33,	0x0FF00FF0),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x9966CC33,	0xF00FF00F),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x669933CC,	0x0FF00FF0),
	DCL_TEST3(TUint32,	AXO,	0xAAAAAAAA, 0x669933CC,	0xF00FF00F),

	DCL_TEST3(TUint32,	CAS,	0x00000000, 0x000000FF,	0x99ABCDEE),
	DCL_TEST3(TUint32,	CAS,	0x00000000, 0x00000001,	0x7FFFF711),
	DCL_TEST3(TUint32,	CAS,	0x00000000, 0x00000000,	0x99ABCDEE),
	DCL_TEST3(TUint32,	CAS,	0x00000000, 0x00000000,	0x11234567),
	DCL_TEST3(TUint32,	CAS,	0x8000032A, 0xFFFFFFFF,	0x8000032B),
	DCL_TEST3(TUint32,	CAS,	0x8000032A, 0x00000001,	0x8000032B),
	DCL_TEST3(TUint32,	CAS,	0x8000032A, 0x8000022A,	0x8000032B),
	DCL_TEST3(TUint32,	CAS,	0x8000032A, 0x8000032B,	0x943BFCD1),
	DCL_TEST3(TUint32,	CAS,	0x8000032A, 0x8000032A,	0x8000032B),
	DCL_TEST3(TUint32,	CAS,	0x8000032A, 0x8000032A,	0x943BFCD1),

	DCL_TEST4(TUint32,	TAU,	0x00000000, 0x00000000,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAU,	0x00000001, 0x00000000,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFFF, 0x00000000,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAU,	0x00000000, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAU,	0x00000001, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAU,	0x00000002, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFFF, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFFE, 0xFFFFFFFE,	0x1023144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFEE, 0xFFFFFFFE,	0x1423144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFFF, 0xFFFFFFFE,	0x1423144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAU,	0x00000000, 0xFFFFFFFE,	0x1423144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFFE, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFEE, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFFF, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAU,	0x00000000, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAU,	0xFFFFFFFE, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x7FFFFFFF, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x80000000, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x80000001, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x00000000, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x7FFFFFFE, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x7FFFFFFF, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x80000000, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x80000001, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAU,	0x00000000, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),

	DCL_TEST4(TUint32,	TAS,	0x00000000, 0x00000000,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAS,	0x00000001, 0x00000000,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFFF, 0x00000000,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAS,	0x00000000, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAS,	0x00000001, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAS,	0x00000002, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFFF, 0x00000001,	0x00000002, 0x00000003),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFFE, 0xFFFFFFFE,	0x1023144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFEE, 0xFFFFFFFE,	0x1423144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFFF, 0xFFFFFFFE,	0x1423144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAS,	0x00000000, 0xFFFFFFFE,	0x1423144F, 0x0000000B),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFFE, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFEE, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFFF, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAS,	0x00000000, 0xFFFFFFFE,	0x80000000, 0x7FFFFFFF),
	DCL_TEST4(TUint32,	TAS,	0xFFFFFFFE, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x7FFFFFFF, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x80000000, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x80000001, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x00000000, 0x80000000,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x7FFFFFFE, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x7FFFFFFF, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x80000000, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x80000001, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE),
	DCL_TEST4(TUint32,	TAS,	0x00000000, 0x7FFFFFFF,	0x80000001, 0x7FFFFFFE)
	};

DCL_TEST_BLOCK(TUint64,TestData64)
	{
	DCL_TEST1(TUint64,	LOAD,	MAKE_TUINT64(0x00000000,0x00000000)),
	DCL_TEST1(TUint64,	LOAD,	MAKE_TUINT64(0xFEDCBA98,0x76543210)),

	DCL_TEST2(TUint64,	STORE,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	STORE,	MAKE_TUINT64(0xFEDCBA98,0x76543210), MAKE_TUINT64(0x06931471,0x80559945)),

	DCL_TEST2(TUint64,	SWP,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	SWP,	MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	SWP,	MAKE_TUINT64(0xDEADBEEF,0xBAD0BEEF), MAKE_TUINT64(0x06931471,0x80559945)),
	DCL_TEST2(TUint64,	SWP,	MAKE_TUINT64(0xFEDCBA98,0x76543210), MAKE_TUINT64(0x06931471,0x80559945)),

	DCL_TEST2(TUint64,	ADD,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	ADD,	MAKE_TUINT64(0x00000000,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	ADD,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	ADD,	MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),

	DCL_TEST2(TUint64,	AND,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	AND,	MAKE_TUINT64(0x00000000,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	AND,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	AND,	MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),

	DCL_TEST2(TUint64,	IOR,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	IOR,	MAKE_TUINT64(0x00000000,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	IOR,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	IOR,	MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	IOR,	MAKE_TUINT64(0x11111111,0x22222222), MAKE_TUINT64(0x44444444,0x55555555)),

	DCL_TEST2(TUint64,	XOR,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	XOR,	MAKE_TUINT64(0x00000000,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST2(TUint64,	XOR,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	XOR,	MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xFCD1CC9F,0xDB27CC8B)),
	DCL_TEST2(TUint64,	XOR,	MAKE_TUINT64(0x11111111,0x22222222), MAKE_TUINT64(0x44444444,0x77777777)),

	DCL_TEST3(TUint64,	AXO,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000001)),
	DCL_TEST3(TUint64,	AXO,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	AXO,	MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	AXO,	MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	AXO,	MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0xFACEFEED,0xFEEDFACE), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	AXO,	MAKE_TUINT64(0xBAD8BEEF,0xDEADDEAD), MAKE_TUINT64(0xFACEFEED,0xFEEDFACE), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),

	DCL_TEST3(TUint64,	CAS,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	CAS,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000001,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	CAS,	MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	CAS,	MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0x00000001,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	CAS,	MAKE_TUINT64(0x00000001,0x00000000), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),
	DCL_TEST3(TUint64,	CAS,	MAKE_TUINT64(0x00000001,0x00000000), MAKE_TUINT64(0x00000001,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED)),

	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x00000000,0x00000002), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0xFFFFFFFF,0x00000000), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x80000000,0x00000000), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x80000000,0x00000002), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x7FFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x7FFFFFFF,0x00000000), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x7FFFFFFF,0x80000000), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x7FFFFFFF,0x80000002), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x7FFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x7FFFFFFF,0x7FFFFFFF), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x80000000,0x00000000), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x80000000,0x80000000), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x80000000,0x80000001), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAU,	MAKE_TUINT64(0x80000000,0x80000002), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),

	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x00000000,0x00000000), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x00000000,0x00000002), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0xFFFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0xFFFFFFFF,0x00000000), MAKE_TUINT64(0x00000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x80000000,0x00000000), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x80000000,0x00000002), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x7FFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x7FFFFFFF,0x00000000), MAKE_TUINT64(0x80000000,0x00000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x7FFFFFFF,0x80000000), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x7FFFFFFF,0x80000002), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x7FFFFFFF,0xFFFFFFFF), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x7FFFFFFF,0x7FFFFFFF), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x80000000,0x00000000), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x80000000,0x80000000), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x80000000,0x80000001), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5)),
	DCL_TEST4(TUint64,	TAS,	MAKE_TUINT64(0x80000000,0x80000002), MAKE_TUINT64(0x7FFFFFFF,0x80000001), MAKE_TUINT64(0xFEEDFACE,0xFACEFEED), MAKE_TUINT64(0xBAD9BEEF,0x00FAECE5))
	};



template<class T>
void DoTestBlock(const TD<T>* aTests, TInt aCount)
	{
	const TD<T>* p = aTests;
	const TD<T>* e = aTests + aCount;
	for (; p<e; ++p)
		{
		TInt ord;
		for (ord=EOrderRelaxed; ord<=EOrderOrdered; ++ord)
			{
			TDG tdg;
			tdg.Set(*p, ord);
			if (tdg.iIndex<0)
				continue;
#ifdef __EXTRA_DEBUG__
			TPtrC8 fname8((const TText8*)FuncName[tdg.iIndex]);
			TBuf<64> fname;
			fname.Copy(fname8);
			test.Printf(_L("%S\n"), &fname);
#endif
			TInt res;
			res = tdg.ExecuteUser();
			if (res!=0)
				{
				tdg.Dump("ExecuteUser");
				test.Printf(_L("FAIL %d\n"),res);
				test(0);
				}
#ifdef __EPOC32__
#ifdef __EXTRA_DEBUG__
			test.Printf(_L("%S K\n"), &fname);
#endif
			res = tdg.ExecuteKernel();
			if (res!=0)
				{
				tdg.Dump("ExecuteKernel");
				test.Printf(_L("FAIL %d\n"),res);
				test(0);
				}
#endif
			}
		}
	}

#define DO_TEST_BLOCK(type,array)	\
	DoTestBlock<type>(&(array)[0],(TInt)(sizeof(array)/sizeof(TD<type>)))

void TestSingleThread()
	{
	test.Next(_L("8 bit, single thread"));
	DO_TEST_BLOCK(TUint8, TestData8);
	test.Next(_L("16 bit, single thread"));
	DO_TEST_BLOCK(TUint16, TestData16);
	test.Next(_L("32 bit, single thread"));
	DO_TEST_BLOCK(TUint32, TestData32);
	test.Next(_L("64 bit, single thread"));
	DO_TEST_BLOCK(TUint64, TestData64);
	}



/******************************************************************************
 * Test invalid address handling when called from user mode
 ******************************************************************************/
const TLinAddr KSpecialAddr = 0x100u;
const TInt KIndexRead = -1;
const TInt KIndexReadWrite = -2;

struct TE
	{
	static TInt Execute(TInt aIndex, TAny* aPtr1, TAny* aPtr2, TInt aResult);
	TInt DoExecute();
	static TInt ThreadFn(TAny*);

	TInt	iIndex;
	TAny*	iPtr1;
	TAny*	iPtr2;
	};

template<class T> TInt DoLoadErrorTest(TInt aIndex, const T* aPtr)
	{
	typename TLoadFn<T>::F atomic = (typename TLoadFn<T>::F)AtomicFuncPtr[aIndex];
	atomic(aPtr);
	return 0;
	}

template<class T> TInt DoRmw1ErrorTest(TInt aIndex, T* aPtr)
	{
	typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aIndex];
	T a1 = 0;
	atomic(aPtr, a1);
	return 0;
	}

template<class T> TInt DoRmw2ErrorTest(TInt aIndex, T* aPtr)
	{
	typename TRmw2Fn<T>::F atomic = (typename TRmw2Fn<T>::F)AtomicFuncPtr[aIndex];
	T a1 = 0;
	T a2 = 0;
	atomic(aPtr, a1, a2);
	return 0;
	}

template<class T> TInt DoRmw3ErrorTest(TInt aIndex, T* aPtr)
	{
	typename TRmw3Fn<T>::F atomic = (typename TRmw3Fn<T>::F)AtomicFuncPtr[aIndex];
	T a1 = 0;
	T a2 = 0;
	T a3 = 0;
	atomic(aPtr, a1, a2, a3);
	return 0;
	}

template<class T> TInt DoCasErrorTest(TInt aIndex, T* aPtr1, T* aPtr2)
	{
	typename TCasFn<T>::F atomic = (typename TCasFn<T>::F)AtomicFuncPtr[aIndex];
	TLinAddr a1 = (TLinAddr)aPtr1;
	TLinAddr a2 = (TLinAddr)aPtr2;
	T reg;
	T exp;
	T f;
	memset(&f, 0xbb, sizeof(T));
	if ((a1&~0xff)==KSpecialAddr)
		{
		memset(&reg, (a1&0xff), sizeof(T));
		aPtr1 = &reg;
		}
	if ((a2&~0xff)==KSpecialAddr)
		{
		memset(&exp, (a2&0xff), sizeof(T));
		aPtr2 = &exp;
		}
	TInt r = atomic(aPtr1, aPtr2, f);
	return r ? 1 : 0;
	}

TInt TE::DoExecute()
	{
	if (iIndex == KIndexRead)
		{
		return *(volatile TUint8*)iPtr1;
		}
	if (iIndex == KIndexReadWrite)
		{
		volatile TUint8* p = (volatile TUint8*)iPtr1;
		TUint8 x = *p;
		*p = x;
		return 0;
		}
	TUint attr = FuncAttr[iIndex];
	TInt type = ATTR_TO_TYPE(attr);
	TInt size = ATTR_TO_SIZE(attr);
	if (type==EFuncTypeInvalid)
		return KErrNotSupported;
	TInt res;
	switch (type)
		{
		case EFuncTypeLoad:
			{
			switch (size)
				{
				case 1:	res = DoLoadErrorTest<TUint8>(iIndex, (TUint8*)iPtr1); break;
				case 2:	res = DoLoadErrorTest<TUint16>(iIndex, (TUint16*)iPtr1); break;
				case 4:	res = DoLoadErrorTest<TUint32>(iIndex, (TUint32*)iPtr1); break;
				case 8:	res = DoLoadErrorTest<TUint64>(iIndex, (TUint64*)iPtr1); break;
				default: res = KErrNotSupported; break;
				}
			break;
			}
		case EFuncTypeRmw1:
			{
			switch (size)
				{
				case 1:	res = DoRmw1ErrorTest<TUint8>(iIndex, (TUint8*)iPtr1); break;
				case 2:	res = DoRmw1ErrorTest<TUint16>(iIndex, (TUint16*)iPtr1); break;
				case 4:	res = DoRmw1ErrorTest<TUint32>(iIndex, (TUint32*)iPtr1); break;
				case 8:	res = DoRmw1ErrorTest<TUint64>(iIndex, (TUint64*)iPtr1); break;
				default: res = KErrNotSupported; break;
				}
			break;
			}
		case EFuncTypeRmw2:
			{
			switch (size)
				{
				case 1:	res = DoRmw2ErrorTest<TUint8>(iIndex, (TUint8*)iPtr1); break;
				case 2:	res = DoRmw2ErrorTest<TUint16>(iIndex, (TUint16*)iPtr1); break;
				case 4:	res = DoRmw2ErrorTest<TUint32>(iIndex, (TUint32*)iPtr1); break;
				case 8:	res = DoRmw2ErrorTest<TUint64>(iIndex, (TUint64*)iPtr1); break;
				default: res = KErrNotSupported; break;
				}
			break;
			}
		case EFuncTypeRmw3:
			{
			switch (size)
				{
				case 1:	res = DoRmw3ErrorTest<TUint8>(iIndex, (TUint8*)iPtr1); break;
				case 2:	res = DoRmw3ErrorTest<TUint16>(iIndex, (TUint16*)iPtr1); break;
				case 4:	res = DoRmw3ErrorTest<TUint32>(iIndex, (TUint32*)iPtr1); break;
				case 8:	res = DoRmw3ErrorTest<TUint64>(iIndex, (TUint64*)iPtr1); break;
				default: res = KErrNotSupported; break;
				}
			break;
			}
		case EFuncTypeCas:
			{
			switch (size)
				{
				case 1:	res = DoCasErrorTest<TUint8>(iIndex, (TUint8*)iPtr1, (TUint8*)iPtr2); break;
				case 2:	res = DoCasErrorTest<TUint16>(iIndex, (TUint16*)iPtr1, (TUint16*)iPtr2); break;
				case 4:	res = DoCasErrorTest<TUint32>(iIndex, (TUint32*)iPtr1, (TUint32*)iPtr2); break;
				case 8:	res = DoCasErrorTest<TUint64>(iIndex, (TUint64*)iPtr1, (TUint64*)iPtr2); break;
				default: res = KErrNotSupported; break;
				}
			break;
			}
		default:
			res = KErrNotSupported;
			break;
		}
	return res;
	}

TInt TE::ThreadFn(TAny* aPtr)
	{
	return ((TE*)aPtr)->DoExecute();
	}

_LIT(KLitKERNEXEC,"KERN-EXEC");
TInt TE::Execute(TInt aIndex, TAny* aPtr1, TAny* aPtr2, TInt aResult)
	{
	DEBUGPRINT("I=%3d P1=%08x P2=%08x R=%d", aIndex, aPtr1, aPtr2, aResult);
	TE te;
	te.iIndex = aIndex;
	te.iPtr1 = aPtr1;
	te.iPtr2 = aPtr2;
	RThread t;
	TInt r = t.Create(KNullDesC, &ThreadFn, 0x1000, 0, &te);
	test_KErrNone(r);
	TRequestStatus s;
	t.Logon(s);
	test_Equal(KRequestPending, s.Int());
	TBool jit = User::JustInTime();
	User::SetJustInTime(EFalse);
	t.Resume();
	User::WaitForRequest(s);
	User::SetJustInTime(jit);
	TInt xt = t.ExitType();
	TInt xr = t.ExitReason();
	const TDesC& xc = t.ExitCategory();
	DEBUGPRINT("Exit type: %d,%d,%S", xt, xr, &xc);
	TInt res = KErrNone;
	if (aResult == KErrUnknown)
		{
		if (xt==EExitPanic)
			{
			test_Equal(ECausedException, xr);
			test(xc==KLitKERNEXEC);
			res = KErrDied;
			}
		else
			test_Equal(EExitKill, xt);
		}
	else if (aResult == KErrDied)
		{
		test_Equal(EExitPanic, xt);
		test_Equal(ECausedException, xr);
		test(xc==KLitKERNEXEC);
		}
	else
		{
		test_Equal(EExitKill, xt);
		test_Equal(aResult, xr);
		}
	CLOSE_AND_WAIT(t);
	return res;
	}

TInt ThreadAlign(TAny*)
	{
	TUint32 array[2];
	TUint32* p = (TUint32*)(((TLinAddr)array)+1);
	*p = 5;
	return KErrNone;
	}

const TUint64 Zero = UI64LIT(0);
const TUint64 BFBF = UI64LIT(0xbfbfbfbfbfbfbfbf);

void TestInvalidAddresses()
	{
	TAny* bad_addr[11];
	TInt c = 0;
	TInt read_only = 0;
	TInt alignmentEnd = 0;
	TInt mminfo = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0);
//	TInt mmtype = mminfo & EMemModelTypeMask;
#ifdef __EPOC32__
	if (mminfo & EMemModelAttrWriteProt)
		{
		bad_addr[c++] = (TAny*)UserSvr::RomHeaderAddress();
		bad_addr[c++] = (TAny*)&Zero;
		bad_addr[c++] = (TAny*)&BFBF;
		read_only = c;
		}
#endif
	if (mminfo & EMemModelAttrNonExProt)
		{
		bad_addr[c++] = 0;	// address 0 is read only on ARM7 cores, nonexistent on others
		if (TE::Execute(KIndexRead, 0, 0, KErrUnknown)==KErrNone)
			read_only = c;	// address 0 is readable
		TLinAddr nonex = 0;
		do	{
			nonex += 0x1000;
			} while (TE::Execute(KIndexRead, (TAny*)nonex, 0, KErrUnknown)==KErrNone);
		bad_addr[c++] = (TAny*)nonex;
		}
#ifdef __EPOC32__
	if (mminfo & EMemModelAttrKernProt)
		{
		bad_addr[c++] = DD.KernelMemoryAddress();
		}
	// If alignment checking is enabled add alignment tests for 64 bit.
	TUint64A alignArray[2];
	RThread t;
	TInt r = t.Create(KNullDesC, &ThreadAlign, 0x1000, 0, NULL);
	test_KErrNone(r);
	TRequestStatus s;
	t.Logon(s);
	test_Equal(KRequestPending, s.Int());
	TBool jit = User::JustInTime();
	User::SetJustInTime(EFalse);
	t.Resume();
	User::WaitForRequest(s);
	User::SetJustInTime(jit);
	TInt xt = t.ExitType();
	TInt xr = t.ExitReason();
	const TDesC& xc = t.ExitCategory();
	if (EExitPanic == xt)
		{// Took an alignment fault so add alignment test.
		test_Equal(ECausedException, xr);
		test(xc==KLitKERNEXEC);
		alignmentEnd = c;
		bad_addr[alignmentEnd++] = (TAny*)(((TUint)&alignArray[0]) + 1);
		bad_addr[alignmentEnd++] = (TAny*)(((TUint)&alignArray[0]) + 2);
		bad_addr[alignmentEnd++] = (TAny*)(((TUint)&alignArray[0]) + 4);
		}
	
#endif
	TInt i;
	TInt allBadAddr = (alignmentEnd)? c+3 : c;
	DEBUGPRINT("%d invalid addresses", allBadAddr);
	for (i=0; i < allBadAddr; ++i)
		{
		if (i<read_only)
			{
			DEBUGPRINT("bad_addr[%d]=%08x (RO)", i, bad_addr[i]);
			}
		else
			{
			DEBUGPRINT("bad_addr[%d]=%08x", i, bad_addr[i]);
			}
		}
	if (c==0)
		return;
	TInt ix;
	for (ix=0; ix<TOTAL_INDEXES; ++ix)
		{
		TUint attr = FuncAttr[ix];
		TUint func = ATTR_TO_FUNC(attr);
		TUint type = ATTR_TO_TYPE(attr);
		if (type==EFuncTypeInvalid)
			continue;
		if (func==TUint(EAtomicFuncCAS))
			{
			// both addresses OK
			TE::Execute(ix, (TAny*)(KSpecialAddr+0), (TAny*)(KSpecialAddr+0), 1);	// should do the swap
			TE::Execute(ix, (TAny*)(KSpecialAddr+0), (TAny*)(KSpecialAddr+1), 0);	// should not do the swap

			// RMW address OK, expected bad
			for (i=0; i<c; ++i)
				{
				TAny* p = bad_addr[i];
				TInt res = (bad_addr[i]==(TAny*)&BFBF) ? 1 : KErrDied;
				TE::Execute(ix, (TAny*)(KSpecialAddr+0xbf), p, res);
				}

			// RMW address bad, expected OK
			for (i=0; i<c; ++i)
				{
				TAny* p = bad_addr[i];
#if defined(__CPU_X86)
				TInt res = KErrDied;	// on X86 location must be writeable
#elif defined(__CPU_ARM)
				TInt res = (i<read_only && bad_addr[i]!=(TAny*)&BFBF) ? 0 : KErrDied;
				// 64-bit operations on platforms that use a slow exec for 64 bit 
				// will always write to bad_addr[i] but other platforms won't.
				if (ATTR_TO_SIZE(attr) == 8)
					res = KErrUnknown;
#else
#error CPU?
#endif
				TE::Execute(ix, p, (TAny*)(KSpecialAddr+0xbf), res);
				}

			// Both addresses bad
			TInt j;
			for (i=0; i<c; ++i)
				{
				for (j=0; j<c; ++j)
					{
					TE::Execute(ix, bad_addr[i], bad_addr[j], KErrDied);
					}
				}
			}
		else
			{
			// just run through all the bad addresses
			for (i=0; i<c; ++i)
				{
				TAny* p = bad_addr[i];
				TBool ro = (i<read_only);
				TInt res = ((func == TUint(EAtomicFuncLOAD)) && ro) ? KErrNone : KErrDied;
				if (func==TUint(EAtomicFuncLOAD) && ATTR_TO_SIZE(attr)==8)
					res = KErrUnknown;	// 64-bit atomic loads may or may not write as well
				TE::Execute(ix, p, 0, res);
				}
			}
// Checks for 8 byte alignment not enabled on old gcc (arm4) as it is not eabi compliant.
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__EABI__)
		if (ATTR_TO_SIZE(attr) == 8)
			{
			for (i = c; i < alignmentEnd; i++)
				{// 64 bit unaligned accesses should cause exceptions if 
				// alignment checking is enabled.
				TE::Execute(ix, bad_addr[i], 0, KErrDied);
				}
			}
#endif
		}
	}



/******************************************************************************
 * Multiple thread normal operation tests
 ******************************************************************************/
class CThread;
class CThreads : public CBase
	{
public:
	static CThreads* New();
	CThreads();
	~CThreads();
	CThread* NewThread(TInt aId);
	void StartTest(TInt aIndex, TBool aKernel);
	void StopTest();
	void Finish();
	TUint32 DoCasTest(TInt aIndex, TBool aKernel, TUint32 aFailLimit);
	void DoRmwTest(TInt aIndex, TBool aKernel, TInt aTime);
	inline TInt NumCpus() const {return iNumCpus;}
private:
	TInt			iNumCpus;
	TInt			iNumThreads;
	CThread*		iThreads[KMaxThreads];
	RSemaphore		iSem;
	volatile TInt	iIndex;
	volatile TBool	iKernel;
	volatile TBool	iStop;
	volatile TUint64 iReg;
	TInt			iFailCount;
	TInt			iTimeslice;
private:
	friend class CThread;
	};

class CThread : public CBase
	{
private:
	CThread();
	~CThread();
	static TInt ThreadFunction(TAny*);
	TInt Run();
	TInt Create();
	void Start();
	void DoTest();
	TUint64 Random();
	void Kick();
private:
	RThread			iThread;
	TInt			iId;
	CThreads*		iThreads;
	TRequestStatus	iStatus;
	TBool			iStarted;
	TPerThread		iPerThread;
	TUint64			iSeed;
private:
	friend class CThreads;
	};

CThreads::CThreads()
	{
	iNumCpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
	iNumThreads = iNumCpus;
	if (iNumThreads<2)
		iNumThreads=2;
	TInt khz;
	TInt r = HAL::Get(HAL::ECPUSpeed, khz);
	if (r==KErrNone)
		iTimeslice = Max(10000000/khz, 100);
	else if (r==KErrNotSupported)
		iTimeslice = 227;
	else
		User::Panic(_L("TIMESLICE"),r);
	}

CThreads::~CThreads()
	{
	TInt i;
	for (i=0; i<iNumThreads; ++i)
		delete iThreads[i];
	iSem.Close();
	}

CThreads* CThreads::New()
	{
	CThreads* p = new CThreads;
	if (p)
		{
		TInt r;
		r = p->iSem.CreateLocal(0);
		TInt i;
		for (i=0; i<p->iNumThreads && r==KErrNone; ++i)
			{
			p->iThreads[i] = p->NewThread(i);
			if (!p->iThreads[i])
				r = KErrNoMemory;
			}
		if (r!=KErrNone)
			{
			delete p;
			return 0;
			}
		p->iStop = ETrue;
		for (i=0; i<p->iNumThreads; ++i)
			p->iThreads[i]->Start();
		}
	return p;
	}

CThread* CThreads::NewThread(TInt aId)
	{
	CThread* t = new CThread;
	if (t)
		{
		t->iId = aId;
		t->iThreads = this;
		TInt r = t->Create();
		if (r!=KErrNone)
			{
			delete t;
			t = 0;
			}
		}
	return t;
	}

void CThreads::StartTest(TInt aIndex, TBool aKernel)
	{
	iIndex = aIndex;
	iKernel = aKernel;
	iReg = 0;
	iStop = EFalse;
#ifdef __EPOC32__
	if (iKernel)
		DD.Initialise(iReg);
#endif
	TInt i;
	for (i=0; i<iNumThreads; ++i)
		iThreads[i]->Kick();
	}

void CThreads::StopTest()
	{
	iStop = ETrue;
	TInt i;
	for (i=0; i<iNumThreads; ++i)
		iSem.Wait();
#ifdef __EPOC32__
	if (iKernel)
		iReg = DD.Retrieve();
#endif
	}

void CThreads::Finish()
	{
	iStop = EFalse;
	iIndex = -1;
	TInt i;
	for (i=0; i<iNumThreads; ++i)
		{
		iThreads[i]->Kick();
		iSem.Wait();
		}
	test(iFailCount==0);
	}

TUint32 CThreads::DoCasTest(TInt aIndex, TBool aKernel, TUint32 aFailLimit)
	{
	TInt i;
	test.Printf(_L("DoCasTest I=%d K=%1d F=%d\n"), aIndex, aKernel, aFailLimit);
	TUint32 initial = User::FastCounter();
	StartTest(aIndex, aKernel);
	FOREVER
		{
		User::AfterHighRes(1000000);
		TUint64 minf = 0;
		--minf;
		for (i=0; i<iNumThreads; ++i)
			{
			CThread* t = iThreads[i];
			test.Printf(_L("T%1d: C=%lu R=%lu\n"), i, t->iPerThread.iDiff, t->iPerThread.iFailCount);
			TUint64 f = t->iPerThread.iFailCount;
			if (f<minf)
				minf=f;
			}
		if (minf>=TUint64(aFailLimit))
			break;
		if (iNumCpus>1)	// 1 second is enough for SMP, except on VMPlayer
			break;
		}
	StopTest();
	TUint32 final = User::FastCounter();
	TUint32 time = final - initial;
	test.Printf(_L("Time %d\n"), time);
	TUint64 total = 0;
	TUint64 txor = 0;
	for (i=0; i<iNumThreads; ++i)
		{
		CThread* t = iThreads[i];
		test.Printf(_L("T%1d: %lu completed %lu retries\n"), i, t->iPerThread.iDiff, t->iPerThread.iFailCount);
		total += t->iPerThread.iDiff;
		txor ^= t->iPerThread.iXor;
		}
	TUint size = ATTR_TO_SIZE(FuncAttr[aIndex]);
	TUint64 expected = 0;
	switch (size)
		{
		case 1:	expected = Transform<TUint8>::F_iter(0, total); break;
		case 2:	expected = Transform<TUint16>::F_iter(0, total); break;
		case 4:	expected = Transform<TUint32>::F_iter(0, total); break;
		case 8:	expected = Transform<TUint64>::F_iter(0, total); break;
		}
	test.Printf(_L("Total iterations %lu\n"), total);
	test.Printf(_L("Expected result %08x %08x\n"), I64HIGH(expected), I64LOW(expected));
	test.Printf(_L("Actual   result %08x %08x\n"), I64HIGH(iReg), I64LOW(iReg));
	test.Printf(_L("Tot. XOR result %08x %08x\n"), I64HIGH(txor), I64LOW(txor));
//	test(expected==iReg);
//	test(expected==txor);
	if (expected!=iReg || expected!=txor)
		{
		test.Printf(_L("***FAIL***\n"));
		++iFailCount;
		}
	return time;
	}

void CThreads::DoRmwTest(TInt aIndex, TBool aKernel, TInt aTime)
	{
	TInt i;
	test.Printf(_L("DoRmwTest I=%d K=%1d T=%d\n"), aIndex, aKernel, aTime);
	StartTest(aIndex, aKernel);
	User::AfterHighRes(aTime);
	StopTest();
	TUint64 total = 0;
	TUint64 txor = 0;
	for (i=0; i<iNumThreads; ++i)
		{
		CThread* t = iThreads[i];
		test.Printf(_L("T%1d: C=%10lu D=%lx X=%lx\n"), i, t->iPerThread.iCount, t->iPerThread.iDiff, t->iPerThread.iXor);
		total += t->iPerThread.iDiff;
		txor ^= t->iPerThread.iXor;
		}
	TUint size = ATTR_TO_SIZE(FuncAttr[aIndex]);
	switch (size)
		{
		case 1:
			{
			TUint8 expected = (TUint8)total;
			TUint8 exor = (TUint8)txor;
			TUint8 got = (TUint8)iReg;
			test.Printf(_L("Expected %02x Got %02x XOR %02x\n"), expected, got, exor);
//			test(expected==got && exor==got);
			if (expected!=got || exor!=got)
				{
				test.Printf(_L("***FAIL***\n"));
				++iFailCount;
				}
			break;
			}
		case 2:
			{
			TUint16 expected = (TUint16)total;
			TUint16 exor = (TUint16)txor;
			TUint16 got = (TUint16)iReg;
			test.Printf(_L("Expected %04x Got %04x XOR %04x\n"), expected, got, exor);
//			test(expected==got && exor==got);
			if (expected!=got || exor!=got)
				{
				test.Printf(_L("***FAIL***\n"));
				++iFailCount;
				}
			break;
			}
		case 4:
			{
			TUint32 expected = (TUint32)total;
			TUint32 exor = (TUint32)txor;
			TUint32 got = (TUint32)iReg;
			test.Printf(_L("Expected %08x Got %08x XOR %08x\n"), expected, got, exor);
//			test(expected==got && exor==got);
			if (expected!=got || exor!=got)
				{
				test.Printf(_L("***FAIL***\n"));
				++iFailCount;
				}
			break;
			}
		case 8:
			{
			TUint64 expected = total;
			test.Printf(_L("Expected result %08x %08x\n"), I64HIGH(expected), I64LOW(expected));
			test.Printf(_L("Actual   result %08x %08x\n"), I64HIGH(iReg), I64LOW(iReg));
			test.Printf(_L("Tot. XOR result %08x %08x\n"), I64HIGH(txor), I64LOW(txor));
//			test(expected==iReg && expected==txor);
			if (expected!=iReg || expected!=txor)
				{
				test.Printf(_L("***FAIL***\n"));
				++iFailCount;
				}
			break;
			}
		}
	}

CThread::CThread()
	{
	}

CThread::~CThread()
	{
	TInt h = iThread.Handle();
	if (h && h!=KCurrentThreadHandle)
		{
		if (!iStarted)
			iThread.Kill(0);
		User::WaitForRequest(iStatus);
		}
	iThread.Close();
	}

TInt CThread::Create()
	{
	TInt r = iThread.Create(KNullDesC, &ThreadFunction, 0x2000, 0, this);
	if (r==KErrNone)
		{
		iThread.Logon(iStatus);
		if (iStatus.Int() != KRequestPending)
			r = iStatus.Int();
		}
	return r;
	}

void CThread::Start()
	{
	iThread.Resume();
	iThreads->iSem.Wait();
	}

void CThread::Kick()
	{
	TRequestStatus s;
	TRequestStatus* pS = &s;
	iThread.RequestComplete(pS,0);
	}

TInt CThread::ThreadFunction(TAny* aPtr)
	{
	return ((CThread*)aPtr)->Run();
	}

TInt CThread::Run()
	{
#ifdef __EPOC32__
	DD.SetCurrentThreadTimeslice(iThreads->iTimeslice);
#endif
	RThread().SetPriority(EPriorityLess);
	FOREVER
		{
		if (iThreads->iStop)
			{
			iThreads->iSem.Signal();
			if (iThreads->iNumCpus > 1)
				RThread().SetPriority(EPriorityAbsoluteHigh);	// encourage spreading out of threads between CPUs
			User::WaitForAnyRequest();
			if (iThreads->iIndex<0)
				break;
			if (iThreads->iNumCpus > 1)
				{
				TUint32 tick = User::NTickCount();
				while(User::NTickCount()-tick < 2) {}	// spin to discourage putting other threads on this CPU
				RThread().SetPriority(EPriorityLess);
				}
			}
		DoTest();
		}
	iThreads->iSem.Signal();
	return 0;
	}

TUint64 CThread::Random()
	{
	iSeed = Transform<TUint64>::F(iSeed);
	return iSeed;
	}

void CThread::DoTest()
	{
	iPerThread.iDiff = 0;
	iPerThread.iXor = 0;
	iPerThread.iFailCount = 0;
	iPerThread.iCount = 0;
	TInt index = iThreads->iIndex;
	TAny* p = (TAny*)&iThreads->iReg;
#ifdef __EPOC32__
	TBool kernel = iThreads->iKernel;
	if (kernel)
		{
		DD.SwitchExecTables(iId);
		RTestAtomic::SetThreadInfo(iPerThread);
		}
	TInt iter = 0;
#endif
	iSeed = iId;
	while (!iThreads->iStop)
		{
		TAtomicAction action;
		action.i0 = Random();
		action.i1 = Random();
		action.i2 = Random();
		action.iIndex = index;
		action.iThread = iId;
#ifdef __EPOC32__
		if (kernel)
			{
			RTestAtomic::AtomicAction(action);
			}
		else
#endif
			DoAtomicAction(p, &iPerThread, action);
#ifdef __EPOC32__
		if (kernel && ++iter==1024)
			{
			iter = 0;
			RTestAtomic::GetThreadInfo(iPerThread);
			}
#endif
		}
#ifdef __EPOC32__
	if (kernel)
		{
		RTestAtomic::GetThreadInfo(iPerThread);
		RTestAtomic::RestoreExecTable();
		}
#endif
	}

void TestMultipleThreads()
	{
	CThreads* p = CThreads::New();
	test(p!=0);

	TInt KRequiredRetries = 1000;
	if (p->NumCpus()==1)
		KRequiredRetries = 10;

	TUint32 time;
	TUint32 total_time = 0;
	TUint32 total_time_k = 0;
	TUint32 count = 0;
	TInt ix;
	for (ix=0; ix<TOTAL_INDEXES; ++ix)
		{
		TUint attr = FuncAttr[ix];
		TUint func = ATTR_TO_FUNC(attr);
		TUint type = ATTR_TO_TYPE(attr);
		if (p->NumCpus()==1)
			{
			TUint ord = ATTR_TO_ORD(attr);
			if (ord != EOrderOrdered)
				continue;
			}
		if (type==EFuncTypeInvalid)
			continue;
		if (func!=TUint(EAtomicFuncCAS))
			continue;
		time = p->DoCasTest(ix, EFalse, KRequiredRetries);
		total_time += time;
		++count;
		time = p->DoCasTest(ix, ETrue, KRequiredRetries);
		total_time_k += time;
		}
	TUint32 avg_time = total_time / count;
	TUint32 avg_time_k = total_time_k / count;
	TUint32 fcf=0;
	TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)fcf);
	test_KErrNone(r);
	test.Printf(_L("FastCounterFrequency = %u\n"), fcf);
	TUint64 avg_time_us64(avg_time);
	avg_time_us64*=UI64LIT(1000000);
	avg_time_us64/=TUint64(fcf);
	TInt avg_time_us = KMaxTInt;
	TInt avg_time_k_us = KMaxTInt;
	if (avg_time_us64<TUint64(KMaxTInt))
		avg_time_us = (TInt)avg_time_us64;
	TUint64 avg_time_k_us64(avg_time);
	avg_time_k_us64*=UI64LIT(1000000);
	avg_time_k_us64/=TUint64(fcf);
	if (avg_time_k_us64<TUint64(KMaxTInt))
		avg_time_k_us = (TInt)avg_time_k_us64;

	test.Printf(_L("Average time (user) %u (%dus)\n"), avg_time, avg_time_us);
	test.Printf(_L("Average time (kernel) %u (%dus)\n"), avg_time_k, avg_time_k_us);

	TInt limit_us = (p->NumCpus()==1) ? 15*1000*1000 : 4*1000*1000;

	for (ix=0; ix<TOTAL_INDEXES; ++ix)
		{
		TUint attr = FuncAttr[ix];
		TUint func = ATTR_TO_FUNC(attr);
		TUint type = ATTR_TO_TYPE(attr);
		if (p->NumCpus()==1)
			{
			TUint ord = ATTR_TO_ORD(attr);
			if (ord != EOrderOrdered)
				continue;
			}
		if (type==EFuncTypeInvalid)
			continue;
		if (func<TUint(EAtomicFuncSWP) || func>=TUint(EAtomicFuncCAS))
			continue;
		if (func==TUint(EAtomicFuncIOR))	// can only test AND and IOR together
			continue;
		p->DoRmwTest(ix, EFalse, Min(avg_time_us,limit_us));
		p->DoRmwTest(ix, ETrue, Min(avg_time_k_us,limit_us));
		}

	p->Finish();
	delete p;
	}



/******************************************************************************
 * Main
 ******************************************************************************/
TInt E32Main()
	{
	test.Title();
	test.Start(_L("Opening device driver"));
#ifdef __EPOC32__
	TInt r;
	r = User::LoadLogicalDevice(KAtomicTestLddName);
	test(r==KErrNone||r==KErrAlreadyExists);
	r = DD.Open();
	test_KErrNone(r);
#endif
	test.Next(_L("Testing atomic operations ..."));
	test.Next(_L("Single thread, normal operation"));
	TestSingleThread();
	test.Next(_L("Single thread, bad addresses"));
	TestInvalidAddresses();
	test.Next(_L("Multiple threads"));
	TestMultipleThreads();
	test.End();
	return 0;
	}