Update contrib.
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\math\t_vfp.cpp
16 // Test the ARM Vector Floating Point operations.
20 // - Check that the HAL agrees with the hardware about whether
22 // - Test setting VFP to IEEE with no exceptions mode, if IEEE mode is
23 // supported, otherwise leave the mode alone.
24 // - Test single and double precision vector floating point operations:
25 // ABS, NEG, ADD, SUB, MUL, DIV, NMUL, SQRT, MAC, MSC, NMAC and NMSC.
26 // Verify results are as expected - if IEEE mode was set, verify
27 // bit-for-bit, in accordance with the IEEE specification, otherwise
28 // use normal floating point equality.
29 // - Test VFP context save.
30 // - Test various VFP operations that cause bounces to support code if
31 // IEEE mode is supported.
32 // - Test setting VFP to RunFast mode if RunFast mode is supported.
33 // - Test setting VFP rounding mode.
34 // - Test inheriting VFP mode to created threads.
35 // Platforms/Drives/Compatibility:
37 // Assumptions/Requirement/Pre-requisites:
38 // Failures and causes:
39 // Base Port information:
44 //! @SYMTestCaseID KBASE-0017-T_VFP
45 //! @SYMTestCaseDesc VFPv2 general functionality and bounce handling
47 //! @SYMTestPriority Critical
48 //! @SYMTestActions Check VFP functions correctly in all modes and that mode switching works correctly.
49 //! @SYMTestExpectedResults Test runs until this message is emitted: RTEST: SUCCESS : T_VFP test completed O.K.
53 #define __E32TEST_EXTENSION__
60 RTest test(_L("T_VFP"));
69 typedef void TSglTest(const TReal32* aArgs, TReal32* aResults);
70 typedef void TDblTest(const TReal64* aArgs, TReal64* aResults);
74 TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalFloatingPointSystemId, &FPSID, NULL);
78 TInt TestVFPInitThreadFn(TAny* aPtr)
80 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)CurrentCpu1, 0);
81 TReal32* p = (TReal32*)aPtr;
88 void TestVFPInitialState()
90 for (CurrentCpu1 = 0; CurrentCpu1 < CPUs; CurrentCpu1++)
94 TInt r = t.Create(KNullDesC, &TestVFPInitThreadFn, 0x1000, NULL, f);
99 User::WaitForRequest(s);
100 TInt xt = t.ExitType();
101 TInt xr = t.ExitReason();
102 test(xt == EExitKill && xr == KErrNone);
104 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)CurrentCpu1, 0);
105 test.Printf(_L("FPSCR = %08x for core %d\n"), Vfp::Fpscr(), CurrentCpu1);
106 const TUint32* p = (const TUint32*)f;
107 for (TInt i=0; i<32; ++i)
111 test.Printf(_L("S%d = 0x%08x\n"), i, p[i]);
118 void TestVFPSglRegs(TInt aIter=2)
126 case ARCH_VERSION_VFPV2:
127 case ARCH_VERSION_VFPV3_SUBARCH_V2:
128 case ARCH_VERSION_VFPV3_SUBARCH_NULL:
129 case ARCH_VERSION_VFPV3_SUBARCH_V3:
134 __ASSERT_ALWAYS(0, User::Panic(_L("Bad VFP version"),__LINE__));
138 for (i=0; i<aIter; ++i)
140 for (j=0; j<nSglRegs; ++j)
145 for (j=0; j<nSglRegs; ++j)
148 TInt32 g = Vfp::SRegInt(j);
154 TInt TestVFPSglRegsThread(TAny*)
156 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)CurrentCpu1, 0);
157 TestVFPSglRegs(KMaxTInt);
161 void TestVFPDblRegs(TInt aIter=2)
169 case ARCH_VERSION_VFPV2:
174 case ARCH_VERSION_VFPV3_SUBARCH_V2:
175 case ARCH_VERSION_VFPV3_SUBARCH_NULL:
176 case ARCH_VERSION_VFPV3_SUBARCH_V3:
179 TInt ret = HAL::Get(HALData::EHardwareFloatingPoint, vfpType);
180 if (ret == KErrNone && vfpType == EFpTypeVFPv3)
188 __ASSERT_ALWAYS(0, User::Panic(_L("Bad VFP version"),__LINE__));
192 for (i=0; i<aIter; ++i)
194 for (j=0; j<nDblRegs; ++j)
196 TInt64 f = i + j + KMaxTUint;
199 for (j=0; j<nDblRegs; ++j)
201 TInt64 f = i + j + KMaxTUint;
202 TInt64 g = Vfp::DRegInt(j);
208 TInt TestVFPDblRegsThread(TAny*)
210 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)CurrentCpu2, 0);
211 TestVFPDblRegs(KMaxTInt);
215 void TestVFPContextSave()
217 for (CurrentCpu2 = 0; CurrentCpu2 < CPUs; CurrentCpu2++)
219 for (CurrentCpu1 = 0; CurrentCpu1 < CPUs; CurrentCpu1++)
221 TThreadFunction tf1 = &TestVFPSglRegsThread;
222 TThreadFunction tf2 = Double ? &TestVFPDblRegsThread : &TestVFPSglRegsThread;
225 r = t1.Create(KNullDesC, tf1, 0x1000, 0x1000, 0x1000, NULL);
227 t1.SetPriority(EPriorityLess);
228 r = t2.Create(KNullDesC, tf2, 0x1000, 0x1000, 0x1000, NULL);
230 t2.SetPriority(EPriorityLess);
231 TRequestStatus s1, s2;
236 test.Printf(_L("Let threads run concurrently (cores %d and %d)\n"), CurrentCpu1, CurrentCpu2);
237 User::After(20*1000*1000/CPUs);
239 test.Printf(_L("Kill threads\n"));
242 User::WaitForRequest(s1);
243 User::WaitForRequest(s2);
244 test(t1.ExitType()==EExitKill && t1.ExitReason()==KErrNone);
245 test(t2.ExitType()==EExitKill && t2.ExitReason()==KErrNone);
252 TInt TestBounceCtxThread1(TAny*)
254 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)Max(CPUs-1, 0), 0);
255 for(TInt iter=0; iter<KMaxTInt; ++iter)
262 TInt TestBounceCtxThread2(TAny*)
264 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)Max(CPUs-1, 0), 0);
265 TInt start_rep = 0x00800000; // smallest single precision normal number, 1*2^-126
266 TReal32 start = *(TReal32*)&start_rep;
267 for(TInt iter=0; iter<KMaxTInt; ++iter)
269 Vfp::SetSReg(start, 1);
270 Vfp::SetSReg(2.0f, 2);
275 TReal32 end = Vfp::SReg(0);
276 TInt end_rep = *(TInt*)&end;
277 if (start_rep != end_rep)
279 RDebug::Printf("mismatch in iter %d, start %08x end %08x\n", iter, start_rep, end_rep);
286 void DoBounceContextSwitchTests()
288 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, 0, 0);
291 r = t1.Create(KNullDesC, &TestBounceCtxThread1, 0x1000, 0x1000, 0x1000, NULL);
293 t1.SetPriority(EPriorityLess);
294 r = t2.Create(KNullDesC, &TestBounceCtxThread2, 0x1000, 0x1000, 0x1000, NULL);
296 t2.SetPriority(EPriorityLess);
297 TRequestStatus s1, s2;
302 test.Printf(_L("Let threads run concurrently ...\n"));
303 User::After(20*1000*1000);
305 test.Printf(_L("Kill threads\n"));
308 User::WaitForRequest(s1);
309 User::WaitForRequest(s2);
310 test(t1.ExitType()==EExitKill && t1.ExitReason()==KErrNone);
311 test(t2.ExitType()==EExitKill && t2.ExitReason()==KErrNone);
316 void TestAbsS(const TReal32* a, TReal32* r)
318 Vfp::SetSReg(a[0], 1);
324 void TestAddS(const TReal32* a, TReal32* r)
326 Vfp::SetSReg(a[0], 1);
327 Vfp::SetSReg(a[1], 2);
333 void TestDivS(const TReal32* a, TReal32* r)
335 Vfp::SetSReg(a[0], 1);
336 Vfp::SetSReg(a[1], 2);
345 void TestMacS(const TReal32* a, TReal32* r)
347 Vfp::SetSReg(a[0], 0);
348 Vfp::SetSReg(a[1], 1);
349 Vfp::SetSReg(a[2], 2);
352 r[1] = a[0] + a[1] * a[2];
355 void TestMscS(const TReal32* a, TReal32* r)
357 Vfp::SetSReg(a[0], 0);
358 Vfp::SetSReg(a[1], 1);
359 Vfp::SetSReg(a[2], 2);
362 r[1] = a[1] * a[2] - a[0];
365 void TestMulS(const TReal32* a, TReal32* r)
367 Vfp::SetSReg(a[0], 1);
368 Vfp::SetSReg(a[1], 2);
377 void TestNegS(const TReal32* a, TReal32* r)
379 Vfp::SetSReg(a[0], 1);
385 void TestNMacS(const TReal32* a, TReal32* r)
387 Vfp::SetSReg(a[0], 0);
388 Vfp::SetSReg(a[1], 1);
389 Vfp::SetSReg(a[2], 2);
392 r[1] = a[0] - a[1] * a[2];
395 void TestNMscS(const TReal32* a, TReal32* r)
397 Vfp::SetSReg(a[0], 0);
398 Vfp::SetSReg(a[1], 1);
399 Vfp::SetSReg(a[2], 2);
402 r[1] = -a[1] * a[2] - a[0];
405 void TestNMulS(const TReal32* a, TReal32* r)
407 Vfp::SetSReg(a[0], 1);
408 Vfp::SetSReg(a[1], 2);
417 void TestSqrtS(const TReal32* a, TReal32* r)
419 Vfp::SetSReg(a[0], 1);
428 void TestSubS(const TReal32* a, TReal32* r)
430 Vfp::SetSReg(a[0], 1);
431 Vfp::SetSReg(a[1], 2);
439 void TestAbsD(const TReal64* a, TReal64* r)
441 Vfp::SetDReg(a[0], 1);
447 void TestAddD(const TReal64* a, TReal64* r)
449 Vfp::SetDReg(a[0], 1);
450 Vfp::SetDReg(a[1], 2);
456 void TestDivD(const TReal64* a, TReal64* r)
458 Vfp::SetDReg(a[0], 1);
459 Vfp::SetDReg(a[1], 2);
468 void TestMacD(const TReal64* a, TReal64* r)
470 Vfp::SetDReg(a[0], 0);
471 Vfp::SetDReg(a[1], 1);
472 Vfp::SetDReg(a[2], 2);
475 r[1] = a[0] + a[1] * a[2];
478 void TestMscD(const TReal64* a, TReal64* r)
480 Vfp::SetDReg(a[0], 0);
481 Vfp::SetDReg(a[1], 1);
482 Vfp::SetDReg(a[2], 2);
485 r[1] = a[1] * a[2] - a[0];
488 void TestMulD(const TReal64* a, TReal64* r)
490 Vfp::SetDReg(a[0], 1);
491 Vfp::SetDReg(a[1], 2);
500 void TestNegD(const TReal64* a, TReal64* r)
502 Vfp::SetDReg(a[0], 1);
508 void TestNMacD(const TReal64* a, TReal64* r)
510 Vfp::SetDReg(a[0], 0);
511 Vfp::SetDReg(a[1], 1);
512 Vfp::SetDReg(a[2], 2);
515 r[1] = a[0] - a[1] * a[2];
518 void TestNMscD(const TReal64* a, TReal64* r)
520 Vfp::SetDReg(a[0], 0);
521 Vfp::SetDReg(a[1], 1);
522 Vfp::SetDReg(a[2], 2);
525 r[1] = -a[1] * a[2] - a[0];
528 void TestNMulD(const TReal64* a, TReal64* r)
530 Vfp::SetDReg(a[0], 1);
531 Vfp::SetDReg(a[1], 2);
540 void TestSqrtD(const TReal64* a, TReal64* r)
542 Vfp::SetDReg(a[0], 1);
551 void TestSubD(const TReal64* a, TReal64* r)
553 Vfp::SetDReg(a[0], 1);
554 Vfp::SetDReg(a[1], 2);
560 #define DO_SGL_TEST1(name, func, a1) DoSglTest(name, __LINE__, func, a1)
561 #define DO_SGL_TEST2(name, func, a1, a2) DoSglTest(name, __LINE__, func, a1, a2)
562 #define DO_SGL_TEST3(name, func, a1, a2, a3) DoSglTest(name, __LINE__, func, a1, a2, a3)
563 void DoSglTest(const char* aName, TInt aLine, TSglTest aFunc, TReal32 a1, TReal32 a2=0.0f, TReal32 a3=0.0f)
565 TPtrC8 name8((const TText8*)aName);
568 test.Printf(_L("%S(%g,%g,%g)\n"), &name16, a1, a2, a3);
569 TReal32 args[3] = {a1, a2, a3};
571 (*aFunc)(args, results);
574 if (*((TUint32*)&(results[0])) == *((TUint32*)&(results[1])))
579 if (results[0] == results[1])
582 const TUint32* pa = (const TUint32*)args;
583 const TUint32* pr = (const TUint32*)results;
584 test.Printf(_L("a1=%08x a2=%08x a3=%08x\n"), pa[0], pa[1], pa[2]);
585 test.Printf(_L("actual result = %08x (%g)\nexpected result = %08x (%g)\n"), pr[0], results[0], pr[1], results[1]);
586 test.Printf(_L("Test at line %d failed\n"), aLine);
593 DO_SGL_TEST1("ABS", &TestAbsS, 1.0f);
594 DO_SGL_TEST1("ABS", &TestAbsS, -1.0f);
595 DO_SGL_TEST1("ABS", &TestAbsS, 0.0f);
596 DO_SGL_TEST1("ABS", &TestAbsS, -3.1415926536f);
599 DO_SGL_TEST1("NEG", &TestNegS, 1.0f);
600 DO_SGL_TEST1("NEG", &TestNegS, -1.0f);
601 DO_SGL_TEST1("NEG", &TestNegS, 0.0f);
602 DO_SGL_TEST1("NEG", &TestNegS, -3.1415926536f);
605 DO_SGL_TEST2("ADD", &TestAddS, 0.0f, 0.0f);
606 DO_SGL_TEST2("ADD", &TestAddS, 0.0f, 1.0f);
607 DO_SGL_TEST2("ADD", &TestAddS, -1.0f, 1.0f);
608 DO_SGL_TEST2("ADD", &TestAddS, 1.0f, 2.5f);
609 DO_SGL_TEST2("ADD", &TestAddS, 1.0f, 6.022045e23f);
610 DO_SGL_TEST2("ADD", &TestAddS, -7.3890561f, 1.414213562f);
611 DO_SGL_TEST2("ADD", &TestAddS, -7.3890561f, -1.414213562f);
614 DO_SGL_TEST2("SUB", &TestSubS, 0.0f, 0.0f);
615 DO_SGL_TEST2("SUB", &TestSubS, 0.0f, 1.0f);
616 DO_SGL_TEST2("SUB", &TestSubS, 1.0f, 1.0f);
617 DO_SGL_TEST2("SUB", &TestSubS, 1.0f, 2.5f);
618 DO_SGL_TEST2("SUB", &TestSubS, 91.0f, 2.5f);
619 DO_SGL_TEST2("SUB", &TestSubS, 1.0f, 6.022045e23f);
620 DO_SGL_TEST2("SUB", &TestSubS, -7.3890561f, 1.414213562f);
621 DO_SGL_TEST2("SUB", &TestSubS, -7.3890561f, -1.414213562f);
624 DO_SGL_TEST2("MUL", &TestMulS, 0.0f, 0.0f);
625 DO_SGL_TEST2("MUL", &TestMulS, 1.0f, 0.0f);
626 DO_SGL_TEST2("MUL", &TestMulS, 0.0f, 1.0f);
627 DO_SGL_TEST2("MUL", &TestMulS, 2.5f, 6.5f);
628 DO_SGL_TEST2("MUL", &TestMulS, -39.6f, 19.72f);
629 DO_SGL_TEST2("MUL", &TestMulS, -10.1f, -20.1f);
630 DO_SGL_TEST2("MUL", &TestMulS, 1e20f, 1e20f);
631 DO_SGL_TEST2("MUL", &TestMulS, 1e-30f, 1e-30f);
634 DO_SGL_TEST2("DIV", &TestDivS, 0.0f, 1.0f);
635 DO_SGL_TEST2("DIV", &TestDivS, 1.0f, 5.0f);
636 DO_SGL_TEST2("DIV", &TestDivS, 1.0f, -5.0f);
637 DO_SGL_TEST2("DIV", &TestDivS, -1.0f, 5.0f);
638 DO_SGL_TEST2("DIV", &TestDivS, -1.0f, -5.0f);
639 DO_SGL_TEST2("DIV", &TestDivS, 7.3890561f, 2.7182818f);
640 DO_SGL_TEST2("DIV", &TestDivS, 1e20f, 1e-20f);
641 DO_SGL_TEST2("DIV", &TestDivS, 1e-30f, 1e30f);
644 DO_SGL_TEST2("NMUL", &TestNMulS, 0.0f, 0.0f);
645 DO_SGL_TEST2("NMUL", &TestNMulS, 1.0f, 0.0f);
646 DO_SGL_TEST2("NMUL", &TestNMulS, 0.0f, 1.0f);
647 DO_SGL_TEST2("NMUL", &TestNMulS, 2.5f, 6.5f);
648 DO_SGL_TEST2("NMUL", &TestNMulS, -39.6f, 19.72f);
649 DO_SGL_TEST2("NMUL", &TestNMulS, -10.1f, -20.1f);
650 DO_SGL_TEST2("NMUL", &TestNMulS, 1e20f, 1e20f);
651 DO_SGL_TEST2("NMUL", &TestNMulS, 1e-30f, 1e-30f);
654 DO_SGL_TEST1("SQRT", &TestSqrtS, 0.0f);
655 DO_SGL_TEST1("SQRT", &TestSqrtS, 1.0f);
656 DO_SGL_TEST1("SQRT", &TestSqrtS, 2.0f);
657 DO_SGL_TEST1("SQRT", &TestSqrtS, 3.0f);
658 DO_SGL_TEST1("SQRT", &TestSqrtS, 9096256.0f);
659 DO_SGL_TEST1("SQRT", &TestSqrtS, 1e36f);
660 DO_SGL_TEST1("SQRT", &TestSqrtS, 1e-36f);
663 DO_SGL_TEST3("MAC", &TestMacS, 0.0f, 0.0f, 0.0f);
664 DO_SGL_TEST3("MAC", &TestMacS, 0.0f, 1.0f, 0.0f);
665 DO_SGL_TEST3("MAC", &TestMacS, 0.0f, 1.0f, 1.0f);
666 DO_SGL_TEST3("MAC", &TestMacS, -1.0f, 1.0f, 1.0f);
667 DO_SGL_TEST3("MAC", &TestMacS, 0.8f, 0.1f, 8.0f);
668 DO_SGL_TEST3("MAC", &TestMacS, 0.8f, -0.1f, 8.0f);
669 DO_SGL_TEST3("MAC", &TestMacS, -0.8f, -0.1f, -8.0f);
670 DO_SGL_TEST3("MAC", &TestMacS, 0.8f, 0.3333333333f, 3.1415926536f);
673 DO_SGL_TEST3("MSC", &TestMscS, 0.0f, 0.0f, 0.0f);
674 DO_SGL_TEST3("MSC", &TestMscS, 0.0f, 1.0f, 0.0f);
675 DO_SGL_TEST3("MSC", &TestMscS, 0.0f, 1.0f, 1.0f);
676 DO_SGL_TEST3("MSC", &TestMscS, -1.0f, 1.0f, 1.0f);
677 DO_SGL_TEST3("MSC", &TestMscS, 0.8f, 0.1f, 8.0f);
678 DO_SGL_TEST3("MSC", &TestMscS, 0.8f, -0.1f, 8.0f);
679 DO_SGL_TEST3("MSC", &TestMscS, -0.8f, -0.1f, -8.0f);
680 DO_SGL_TEST3("MSC", &TestMscS, 0.8f, 0.3333333333f, 3.1415926536f);
683 DO_SGL_TEST3("NMAC", &TestNMacS, 0.0f, 0.0f, 0.0f);
684 DO_SGL_TEST3("NMAC", &TestNMacS, 0.0f, 1.0f, 0.0f);
685 DO_SGL_TEST3("NMAC", &TestNMacS, 0.0f, 1.0f, 1.0f);
686 DO_SGL_TEST3("NMAC", &TestNMacS, -1.0f, 1.0f, 1.0f);
687 DO_SGL_TEST3("NMAC", &TestNMacS, 0.8f, 0.1f, 8.0f);
688 DO_SGL_TEST3("NMAC", &TestNMacS, 0.8f, -0.1f, 8.0f);
689 DO_SGL_TEST3("NMAC", &TestNMacS, -0.8f, -0.1f, -8.0f);
690 DO_SGL_TEST3("NMAC", &TestNMacS, 0.8f, 0.3333333333f, 3.1415926536f);
693 DO_SGL_TEST3("NMSC", &TestNMscS, 0.0f, 0.0f, 0.0f);
694 DO_SGL_TEST3("NMSC", &TestNMscS, 0.0f, 1.0f, 0.0f);
695 DO_SGL_TEST3("NMSC", &TestNMscS, 0.0f, 1.0f, 1.0f);
696 DO_SGL_TEST3("NMSC", &TestNMscS, -1.0f, 1.0f, 1.0f);
697 DO_SGL_TEST3("NMSC", &TestNMscS, 0.8f, 0.1f, 8.0f);
698 DO_SGL_TEST3("NMSC", &TestNMscS, 0.8f, -0.1f, 8.0f);
699 DO_SGL_TEST3("NMSC", &TestNMscS, -0.8f, -0.1f, -8.0f);
700 DO_SGL_TEST3("NMSC", &TestNMscS, 0.8f, 0.3333333333f, 3.1415926536f);
703 #define DO_DBL_TEST1(name, func, a1) DoDblTest(name, __LINE__, func, a1)
704 #define DO_DBL_TEST2(name, func, a1, a2) DoDblTest(name, __LINE__, func, a1, a2)
705 #define DO_DBL_TEST3(name, func, a1, a2, a3) DoDblTest(name, __LINE__, func, a1, a2, a3)
706 void DoDblTest(const char* aName, TInt aLine, TDblTest aFunc, TReal64 a1, TReal64 a2=0.0, TReal64 a3=0.0)
708 TPtrC8 name8((const TText8*)aName);
711 test.Printf(_L("%S(%g,%g,%g)\n"), &name16, a1, a2, a3);
712 TReal64 args[3] = {a1, a2, a3};
718 (*aFunc)(args, results);
721 if (*((TUint64*)&(results[0])) == *((TUint64*)&(results[1])))
726 if (results[0] == results[1])
730 sres[0] = results[0];
731 sres[1] = results[1];
732 test.Printf(_L("a1=%08x %08x\na2=%08x %08x\na3=%08x %08x\n"), sargs[0].iData[1], sargs[0].iData[0],
733 sargs[1].iData[1], sargs[1].iData[0], sargs[2].iData[1], sargs[2].iData[0]);
734 test.Printf(_L("actual result = %08x %08x (%g)\nexpected result = %08x %08x (%g)\n"),
735 sres[0].iData[1], sres[0].iData[0], results[0], sres[1].iData[1], sres[1].iData[0], results[1]);
736 test.Printf(_L("Test at line %d failed\n"), aLine);
743 DO_DBL_TEST1("ABS", &TestAbsD, 1.0);
744 DO_DBL_TEST1("ABS", &TestAbsD, -1.0);
745 DO_DBL_TEST1("ABS", &TestAbsD, 0.0);
746 DO_DBL_TEST1("ABS", &TestAbsD, -3.1415926536);
749 DO_DBL_TEST1("NEG", &TestNegD, 1.0);
750 DO_DBL_TEST1("NEG", &TestNegD, -1.0);
751 DO_DBL_TEST1("NEG", &TestNegD, 0.0);
752 DO_DBL_TEST1("NEG", &TestNegD, -3.1415926536);
755 DO_DBL_TEST2("ADD", &TestAddD, 0.0, 0.0);
756 DO_DBL_TEST2("ADD", &TestAddD, 0.0, 1.0);
757 DO_DBL_TEST2("ADD", &TestAddD, -1.0, 1.0);
758 DO_DBL_TEST2("ADD", &TestAddD, 1.0, 2.5);
759 DO_DBL_TEST2("ADD", &TestAddD, 1.0, 6.022045e23);
760 DO_DBL_TEST2("ADD", &TestAddD, -7.3890561, 1.414213562);
761 DO_DBL_TEST2("ADD", &TestAddD, -7.3890561, -1.414213562);
764 DO_DBL_TEST2("SUB", &TestSubD, 0.0, 0.0);
765 DO_DBL_TEST2("SUB", &TestSubD, 0.0, 1.0);
766 DO_DBL_TEST2("SUB", &TestSubD, 1.0, 1.0);
767 DO_DBL_TEST2("SUB", &TestSubD, 1.0, 2.5);
768 DO_DBL_TEST2("SUB", &TestSubD, 91.0, 2.5);
769 DO_DBL_TEST2("SUB", &TestSubD, 1.0, 6.022045e23);
770 DO_DBL_TEST2("SUB", &TestSubD, -7.3890561, 1.414213562);
771 DO_DBL_TEST2("SUB", &TestSubD, -7.3890561, -1.414213562);
774 DO_DBL_TEST2("MUL", &TestMulD, 0.0, 0.0);
775 DO_DBL_TEST2("MUL", &TestMulD, 1.0, 0.0);
776 DO_DBL_TEST2("MUL", &TestMulD, 0.0, 1.0);
777 DO_DBL_TEST2("MUL", &TestMulD, 2.5, 6.5);
778 DO_DBL_TEST2("MUL", &TestMulD, -39.6, 19.72);
779 DO_DBL_TEST2("MUL", &TestMulD, -10.1, -20.1);
780 DO_DBL_TEST2("MUL", &TestMulD, 1e20, 1e20);
781 DO_DBL_TEST2("MUL", &TestMulD, 1e100, 1e300);
782 DO_DBL_TEST2("MUL", &TestMulD, 1e-20, 1e-20);
783 DO_DBL_TEST2("MUL", &TestMulD, 1e-200, 1e-300);
786 DO_DBL_TEST2("DIV", &TestDivD, 0.0, 1.0);
787 DO_DBL_TEST2("DIV", &TestDivD, 1.0, 5.0);
788 DO_DBL_TEST2("DIV", &TestDivD, 1.0, -5.0);
789 DO_DBL_TEST2("DIV", &TestDivD, -1.0, 5.0);
790 DO_DBL_TEST2("DIV", &TestDivD, -1.0, -5.0);
791 DO_DBL_TEST2("DIV", &TestDivD, 7.3890561, 2.7182818);
792 DO_DBL_TEST2("DIV", &TestDivD, 1e20, 1e-20);
793 DO_DBL_TEST2("DIV", &TestDivD, 1e-20, 1e20);
794 DO_DBL_TEST2("DIV", &TestDivD, 1e-50, 1e300);
797 DO_DBL_TEST2("NMUL", &TestNMulD, 0.0, 0.0);
798 DO_DBL_TEST2("NMUL", &TestNMulD, 1.0, 0.0);
799 DO_DBL_TEST2("NMUL", &TestNMulD, 0.0, 1.0);
800 DO_DBL_TEST2("NMUL", &TestNMulD, 2.5, 6.5);
801 DO_DBL_TEST2("NMUL", &TestNMulD, -39.6, 19.72);
802 DO_DBL_TEST2("NMUL", &TestNMulD, -10.1, -20.1);
803 DO_DBL_TEST2("NMUL", &TestNMulD, 1e20, 1e20);
804 DO_DBL_TEST2("NMUL", &TestNMulD, 1e100, 1e300);
805 DO_DBL_TEST2("NMUL", &TestNMulD, 1e-20, 1e-20);
806 DO_DBL_TEST2("NMUL", &TestNMulD, 1e-200, 1e-300);
809 DO_DBL_TEST1("SQRT", &TestSqrtD, 0.0);
810 DO_DBL_TEST1("SQRT", &TestSqrtD, 1.0);
811 DO_DBL_TEST1("SQRT", &TestSqrtD, 2.0);
812 DO_DBL_TEST1("SQRT", &TestSqrtD, 3.0);
813 DO_DBL_TEST1("SQRT", &TestSqrtD, 9096256.0);
814 DO_DBL_TEST1("SQRT", &TestSqrtD, 1e36);
815 DO_DBL_TEST1("SQRT", &TestSqrtD, 1e-36);
818 DO_DBL_TEST3("MAC", &TestMacD, 0.0, 0.0, 0.0);
819 DO_DBL_TEST3("MAC", &TestMacD, 0.0, 1.0, 0.0);
820 DO_DBL_TEST3("MAC", &TestMacD, 0.0, 1.0, 1.0);
821 DO_DBL_TEST3("MAC", &TestMacD, -1.0, 1.0, 1.0);
822 DO_DBL_TEST3("MAC", &TestMacD, 0.8, 0.1, 8.0);
823 DO_DBL_TEST3("MAC", &TestMacD, 0.8, -0.1, 8.0);
824 DO_DBL_TEST3("MAC", &TestMacD, -0.8, -0.1, -8.0);
825 DO_DBL_TEST3("MAC", &TestMacD, 0.8, 0.3333333333, 3.1415926536);
828 DO_DBL_TEST3("MSC", &TestMscD, 0.0, 0.0, 0.0);
829 DO_DBL_TEST3("MSC", &TestMscD, 0.0, 1.0, 0.0);
830 DO_DBL_TEST3("MSC", &TestMscD, 0.0, 1.0, 1.0);
831 DO_DBL_TEST3("MSC", &TestMscD, -1.0, 1.0, 1.0);
832 DO_DBL_TEST3("MSC", &TestMscD, 0.8, 0.1, 8.0);
833 DO_DBL_TEST3("MSC", &TestMscD, 0.8, -0.1, 8.0);
834 DO_DBL_TEST3("MSC", &TestMscD, -0.8, -0.1, -8.0);
835 DO_DBL_TEST3("MSC", &TestMscD, 0.8, 0.3333333333, 3.1415926536);
838 DO_DBL_TEST3("NMAC", &TestNMacD, 0.0, 0.0, 0.0);
839 DO_DBL_TEST3("NMAC", &TestNMacD, 0.0, 1.0, 0.0);
840 DO_DBL_TEST3("NMAC", &TestNMacD, 0.0, 1.0, 1.0);
841 DO_DBL_TEST3("NMAC", &TestNMacD, -1.0, 1.0, 1.0);
842 DO_DBL_TEST3("NMAC", &TestNMacD, 0.8, 0.1, 8.0);
843 DO_DBL_TEST3("NMAC", &TestNMacD, 0.8, -0.1, 8.0);
844 DO_DBL_TEST3("NMAC", &TestNMacD, -0.8, -0.1, -8.0);
845 DO_DBL_TEST3("NMAC", &TestNMacD, 0.8, 0.3333333333, 3.1415926536);
848 DO_DBL_TEST3("NMSC", &TestNMscD, 0.0, 0.0, 0.0);
849 DO_DBL_TEST3("NMSC", &TestNMscD, 0.0, 1.0, 0.0);
850 DO_DBL_TEST3("NMSC", &TestNMscD, 0.0, 1.0, 1.0);
851 DO_DBL_TEST3("NMSC", &TestNMscD, -1.0, 1.0, 1.0);
852 DO_DBL_TEST3("NMSC", &TestNMscD, 0.8, 0.1, 8.0);
853 DO_DBL_TEST3("NMSC", &TestNMscD, 0.8, -0.1, 8.0);
854 DO_DBL_TEST3("NMSC", &TestNMscD, -0.8, -0.1, -8.0);
855 DO_DBL_TEST3("NMSC", &TestNMscD, 0.8, 0.3333333333, 3.1415926536);
860 test.Next(_L("Test denormal handling - single"));
861 DO_SGL_TEST2("ADD", &TestAddS, 1e-39f, 1e-39f);
862 test.Next(_L("Test potential underflow - single"));
863 DO_SGL_TEST2("MUL", &TestMulS, 3.162e-20f, 3.162e-20f);
864 // fails on VFPv2 hardware. ARM's library should be fixed
865 // test.Next(_L("Test NaN input - single"));
866 // TReal32 aSingleNaN;
867 // *((TUint32*)&aSingleNaN) = 0x7F9ABCDE;
868 // Vfp::SetSReg(aSingleNaN, 1);
869 // Vfp::SetSReg(aSingleNaN, 2);
871 // TReal32 aSingleResult = Vfp::SReg(0);
872 // test(*((TUint32*)&aSingleResult) == 0x7FDABCDE);
876 test.Next(_L("Test denormal handling - double"));
877 DO_DBL_TEST2("ADD", &TestAddD, 3.1234e-322, 3.1234e-322);
878 test.Next(_L("Test potential underflow - double"));
879 DO_DBL_TEST2("MUL", &TestMulD, 1.767e-161, 1.767e-161);
880 // fails on VFPv2 hardware. ARM's library should be fixed
881 // test.Next(_L("Test NaN input - double"));
882 // TReal64 aDoubleNaN;
883 // *((TUint64*)&aDoubleNaN) = 0x7FF0123456789ABCll;
884 // Vfp::SetDReg(aDoubleNaN, 1);
885 // Vfp::SetDReg(aDoubleNaN, 2);
887 // TReal64 aDoubleResult = Vfp::DReg(0);
888 // test(*((TUint64*)&aDoubleResult) == 0x7FF8123456789ABC);
892 void DoRunFastTests()
894 test.Next(_L("Test flushing denormals to zero - single"));
895 Vfp::SetSReg(1e-39f, 1);
896 Vfp::SetSReg(1e-39f, 2);
898 test(Vfp::SReg(0)==0);
900 test.Next(_L("Test flushing underflow to zero - single"));
901 Vfp::SetSReg(3.162e-20f, 1);
902 Vfp::SetSReg(3.162e-20f, 2);
904 test(Vfp::SReg(0)==0);
906 test.Next(_L("Test default NaNs - single"));
908 *((TUint32*)&aSingleNaN) = 0x7F9ABCDE;
909 Vfp::SetSReg(aSingleNaN, 1);
910 Vfp::SetSReg(aSingleNaN, 2);
912 TReal32 aSingleResult = Vfp::SReg(0);
913 test(*((TUint32*)&aSingleResult) == 0x7FC00000);
917 test.Next(_L("Test flushing denormals to zero - double"));
918 Vfp::SetDReg(3.1234e-322, 1);
919 Vfp::SetDReg(3.1234e-322, 2);
921 test(Vfp::DReg(0)==0);
923 test.Next(_L("Test flushing underflow to zero - double"));
924 Vfp::SetDReg(1.767e-161, 1);
925 Vfp::SetDReg(1.767e-161, 2);
927 test(Vfp::DReg(0)==0);
929 test.Next(_L("Test default NaNs - double"));
931 *((TUint64*)&aDoubleNaN) = 0x7FF0123456789ABCll;
932 Vfp::SetDReg(aDoubleNaN, 1);
933 Vfp::SetDReg(aDoubleNaN, 2);
935 TReal64 aDoubleResult = Vfp::DReg(0);
936 test(*((TUint64*)&aDoubleResult) == 0x7FF8000000000000ll);
940 void TestAddSResult(const TReal32 a, const TReal32 b, const TReal32 r)
945 test(Vfp::SReg(0) == r);
948 void DoRoundingTests()
950 TFloatingPointMode fpmode = IEEEMode ? EFpModeIEEENoExceptions : EFpModeRunFast;
951 test.Next(_L("Check default rounding to nearest"));
952 test(User::SetFloatingPointMode(fpmode) == KErrNone);
953 test.Next(_L("Check nearest-downward"));
954 TestAddSResult(16777215, 0.49f, 16777215);
955 test.Next(_L("Check nearest-upward"));
956 TestAddSResult(16777215, 0.51f, 16777216);
957 test.Next(_L("Set rounding mode to toward-plus-infinity"));
958 test(User::SetFloatingPointMode(fpmode, EFpRoundToPlusInfinity) == KErrNone);
959 test.Next(_L("Check positive rounding goes upward"));
960 TestAddSResult(16777215, 0.49f, 16777216);
961 test.Next(_L("Check negative rounding goes upward"));
962 TestAddSResult(-16777215, -0.51f, -16777215);
963 test.Next(_L("Set rounding mode to toward-minus-infinity"));
964 test(User::SetFloatingPointMode(fpmode, EFpRoundToMinusInfinity) == KErrNone);
965 test.Next(_L("Check positive rounding goes downward"));
966 TestAddSResult(16777215, 0.51f, 16777215);
967 test.Next(_L("Check negative rounding goes downward"));
968 TestAddSResult(-16777215, -0.49f, -16777216);
969 test.Next(_L("Set rounding mode to toward-zero"));
970 test(User::SetFloatingPointMode(fpmode, EFpRoundToZero) == KErrNone);
971 test.Next(_L("Check positive rounding goes downward"));
972 TestAddSResult(16777215, 0.51f, 16777215);
973 test.Next(_L("Check negative rounding goes upward"));
974 TestAddSResult(-16777215, -0.51f, -16777215);
977 TInt RunFastThread(TAny* /*unused*/)
979 Vfp::SetSReg(1e-39f, 1);
980 Vfp::SetSReg(1e-39f, 2);
982 return (Vfp::SReg(0)==0) ? KErrNone : KErrGeneral;
985 TInt IEEECompliantThread(TAny* /*unused*/)
987 Vfp::SetSReg(1e-39f, 1);
988 Vfp::SetSReg(1e-39f, 2);
990 return (Vfp::SReg(0)==2e-39f) ? KErrNone : KErrGeneral;
993 void TestVFPModeInheritance()
995 test.Printf(_L("Set floating point mode to RunFast\n"));
996 test(User::SetFloatingPointMode(EFpModeRunFast)==KErrNone);
998 TInt r = t.Create(KNullDesC, &RunFastThread, 0x1000, NULL, NULL);
1002 test.Printf(_L("Run RunFast test in another thread...\n"));
1004 test.Printf(_L("Wait for other thread to terminate\n"));
1005 User::WaitForRequest(s);
1006 test(t.ExitType() == EExitKill);
1007 test(s == KErrNone);
1009 test.Printf(_L("Set floating point mode to IEEE\n"));
1010 test(User::SetFloatingPointMode(EFpModeIEEENoExceptions)==KErrNone);
1011 r = t.Create(KNullDesC, &IEEECompliantThread, 0x1000, NULL, NULL);
1014 test.Printf(_L("Run IEEE test in another thread...\n"));
1016 test.Printf(_L("Wait for other thread to terminate\n"));
1017 User::WaitForRequest(s);
1018 test(t.ExitType() == EExitKill);
1019 test(s == KErrNone);
1026 test.Next(_L("Transferring to and from fixed point"));
1028 Vfp::SetSReg(2.5f, 0);
1029 test(Vfp::SReg(0)==2.5f);
1030 Vfp::ToFixedS(3); // Convert to fixed (3) precision
1031 test(Vfp::SRegInt(0)==0x14); // 10.100 in binary fixed(3) format
1032 Vfp::FromFixedS(3); //Convert from fixed (3) precision
1033 test(Vfp::SReg(0)==2.5f);
1036 test.Next(_L("Setting immediate value to floating point registers"));
1038 Vfp::SetSReg(5.0f, 0);
1039 test(Vfp::SReg(0) == 5.0f);
1041 test(Vfp::SReg(0) == 2.0f);
1042 Vfp::SetSReg(5.0f, 0);
1044 test(Vfp::SReg(0) == 2.875f);
1046 Vfp::SetDReg(5.0f, 0);
1047 test(Vfp::DReg(0) == 5.0f);
1049 test(Vfp::DReg(0) == 2.0f);
1051 test(Vfp::DReg(0) == 2.875f);
1058 test.Next(_L("Test creating a thread to execute an F2-prefix instruction"));
1059 test_KErrNone(t.Create(KNullDesC, &NeonWithF2, 0x1000, NULL, NULL));
1062 User::WaitForRequest(s);
1063 test(t.ExitType() == EExitKill);
1064 test(s == KErrNone);
1066 test.Next(_L("Test creating a thread to execute an F3-prefix instruction"));
1067 test_KErrNone(t.Create(KNullDesC, &NeonWithF3, 0x1000, NULL, NULL));
1070 User::WaitForRequest(s);
1071 test(t.ExitType() == EExitKill);
1072 test(s == KErrNone);
1074 test.Next(_L("Test creating a thread to execute an F4x-prefix instruction"));
1075 test_KErrNone(t.Create(KNullDesC, &NeonWithF4x, 0x1000, NULL, NULL));
1078 User::WaitForRequest(s);
1079 test(t.ExitType() == EExitKill);
1080 test(s == KErrNone);
1090 test_KErrNone(t.Create(KNullDesC, &ThumbMode, 0x1000, NULL, (TAny*)testStep++));
1093 User::WaitForRequest(s);
1094 test(s == KErrNone || s == 1);
1095 test(t.ExitType() == EExitKill);
1098 while (s == KErrNone);
1101 test(testStep == 7);
1104 TInt TestThreadMigration(TAny* aPtr)
1106 const TInt inc = (TInt)aPtr;
1107 for (TInt32 switches = 0; switches < KMaxTInt; switches += inc)
1109 Vfp::SetSReg(switches, switches % 16);
1110 UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)(switches % CPUs), 0);
1111 test(Vfp::SRegInt(switches % 16) == switches);
1120 test.Start(_L("Ask HAL if we have hardware floating point"));
1122 CPUs = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
1123 TInt supportedTypes;
1124 TInt HalVfp = HAL::Get(HALData::EHardwareFloatingPoint, supportedTypes);
1125 if (HalVfp == KErrNone)
1127 if (supportedTypes == EFpTypeVFPv2)
1129 test.Printf(_L("HAL reports VFPv2\n"));
1131 else if (supportedTypes == EFpTypeVFPv3)
1133 test.Printf(_L("HAL reports VFPv3\n"));
1135 else if (supportedTypes == EFpTypeVFPv3D16)
1137 test.Printf(_L("HAL reports VFPv3-D16\n"));
1141 test.Printf(_L("HAL reports an unknown floating point type\n"));
1147 test.Printf(_L("HAL reports no VFP support\n"));
1150 test.Next(_L("Check VFP present"));
1151 TBool present = DetectVFP();
1154 test.Printf(_L("No VFP detected\n"));
1155 test(HalVfp == KErrNotSupported ||
1156 ((supportedTypes != EFpTypeVFPv2) &&
1157 (supportedTypes != EFpTypeVFPv3) &&
1158 (supportedTypes != EFpTypeVFPv3D16))
1164 test.Printf(_L("VFP detected. FPSID = %08x\n"), FPSID);
1165 test(HalVfp == KErrNone);
1167 // Verify that the HAL architecture ID matches the FPSID values
1168 // ARMv7 redefines some of these bits so the masks are different :(
1169 if (supportedTypes == EFpTypeVFPv2)
1171 // assume armv5/6's bit definitions, where 19:16 are the arch version
1172 // and 20 is the single-precision-only bit
1173 ArchVersion = (FPSID >> 16) & 0xf;
1174 test(ArchVersion == ARCH_VERSION_VFPV2);
1175 Double = !(FPSID & VFP_FPSID_SNG);
1177 else if (supportedTypes == EFpTypeVFPv3 || supportedTypes == EFpTypeVFPv3D16)
1179 // assume armv7's bit definitions, where 22:16 are the arch version
1180 ArchVersion = (FPSID >> 16) & 0x7f;
1181 test(ArchVersion == ARCH_VERSION_VFPV3_SUBARCH_V2
1182 || ArchVersion == ARCH_VERSION_VFPV3_SUBARCH_NULL
1183 || ArchVersion == ARCH_VERSION_VFPV3_SUBARCH_V3);
1184 // there are bits for this in MVFR0 but ARM implementations should always have it?
1189 test.Printf(_L("Both single and double precision supported\n"), FPSID);
1191 test.Printf(_L("Only single precision supported\n"), FPSID);
1193 test.Next(_L("Test VFP Initial State"));
1194 TestVFPInitialState();
1196 test.Next(_L("Test setting VFP to IEEE no exceptions mode"));
1197 IEEEMode = User::SetFloatingPointMode(EFpModeIEEENoExceptions) == KErrNone;
1199 test.Printf(_L("IEEE no exceptions mode not supported, continuing in RunFast\n"));
1201 test.Next(_L("Test VFP calculations - single"));
1205 test.Next(_L("Test VFP calculations - double"));
1209 test.Next(_L("Test VFP Context Save"));
1210 TestVFPContextSave();
1214 test.Next(_L("Test bounce handling"));
1216 test.Next(_L("Test bouncing while context switching"));
1217 DoBounceContextSwitchTests();
1218 test.Next(_L("Test setting VFP to RunFast mode"));
1219 test(User::SetFloatingPointMode(EFpModeRunFast) == KErrNone);
1223 test.Next(_L("Test VFP rounding modes"));
1228 test.Next(_L("Test VFP mode inheritance between threads"));
1229 TestVFPModeInheritance();
1232 if (supportedTypes == EFpTypeVFPv3 || supportedTypes == EFpTypeVFPv3D16)
1234 test.Next(_L("Test VFPv3"));
1237 if (supportedTypes == EFpTypeVFPv3)
1239 test.Next(_L("Test NEON"));
1242 #if defined(__SUPPORT_THUMB_INTERWORKING)
1243 test.Next(_L("Test Thumb Decode"));
1251 test.Next(_L("Test SMP Thread Migration"));
1254 TRequestStatus s[8];
1256 for (count = 0; count < CPUs + 1; count++)
1258 TInt r = t[count].Create(KNullDesC, &TestThreadMigration, 0x1000, NULL, (TAny*)(inc++));
1260 t[count].Logon(s[count]);
1262 for (count = 0; count < CPUs + 1; count++)
1266 User::After(10*1000*1000);
1267 for (count = 0; count < CPUs + 1; count++)
1271 for (count = 0; count < CPUs + 1; count++)
1273 User::WaitForAnyRequest();
1275 for (count = 0; count < CPUs + 1; count++)
1277 TInt xt = t[count].ExitType();
1278 TInt xr = t[count].ExitReason();
1279 test(xt == EExitKill && xr == KErrNone);
1281 for (count = 0; count < CPUs + 1; count++)
1283 CLOSE_AND_WAIT(t[count]);