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(®, (a1&0xff), sizeof(T));
aPtr1 = ®
}
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;
}