You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
1
(1) |
2
(1) |
3
(5) |
4
(4) |
5
(7) |
6
(4) |
|
7
(3) |
8
(5) |
9
|
10
(5) |
11
|
12
(4) |
13
|
|
14
|
15
(3) |
16
(1) |
17
(2) |
18
|
19
(1) |
20
|
|
21
(1) |
22
|
23
|
24
|
25
|
26
(3) |
27
|
|
28
(2) |
29
(1) |
30
|
31
|
|
|
|
|
From: <sv...@va...> - 2016-08-15 21:54:18
|
Author: carll
Date: Mon Aug 15 22:54:04 2016
New Revision: 15938
Log:
Power PC test suite for ISA 3.0, part 5 of 5
The test suite support for the Power PC ISA 3.0 instructions added in
VEX commit 3244 is added in this commit.
bugzilla 364948
Modified:
trunk/NEWS
trunk/memcheck/mc_translate.c
trunk/memcheck/tests/vbit-test/irops.c
trunk/none/tests/ppc64/ppc64_helpers.h
trunk/none/tests/ppc64/test_isa_3_0.c
trunk/none/tests/ppc64/test_isa_3_0_altivec.stdout.exp
trunk/none/tests/ppc64/test_isa_3_0_other.stdout.exp
trunk/tests/min_power_isa.c
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Mon Aug 15 22:54:04 2016
@@ -142,6 +142,11 @@
365273 Invalid write to stack location reported after signal handler runs
365912 ppc64BE segfault during jm-insns test (RELRO)
366344 Multiple unhandled instruction for Aarch64
+359767 Valgrind does not support the IBM POWER ISA 3.0 instructions, part 1/5
+361207 Valgrind does not support the IBM POWER ISA 3.0 instructions, part 2/5
+362329 Valgrind does not support the IBM POWER ISA 3.0 instructions, part 3/5
+363858 Valgrind does not support the IBM POWER ISA 3.0 instructions, part 4/5
+364948 Valgrind does not support the IBM POWER ISA 3.0 instructions, part 5/5
n-i-bz Fix incorrect (or infinite loop) unwind on RHEL7 x86 and amd64
n-i-bz massif --pages-as-heap=yes does not report peak caused by mmap+munmap
Modified: trunk/memcheck/mc_translate.c
==============================================================================
--- trunk/memcheck/mc_translate.c (original)
+++ trunk/memcheck/mc_translate.c Mon Aug 15 22:54:04 2016
@@ -1461,7 +1461,6 @@
ty = typeOfIRExpr(mce->sb->tyenv, vatom);
tl_assert(ty != Ity_I1);
- tl_assert(ty != Ity_I128);
if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
/* later: no ... */
/* emit code to emit a complaint if any of the vbits are 1. */
@@ -1783,8 +1782,25 @@
operation. Here are some special cases which use PCast only
twice rather than three times. */
- /* I32 x I64 x I64 x I64 -> I64 */
/* Standard FP idiom: rm x FParg1 x FParg2 x FParg3 -> FPresult */
+
+ if (t1 == Ity_I32 && t2 == Ity_I128 && t3 == Ity_I128 && t4 == Ity_I128
+ && finalVty == Ity_I128) {
+ if (0) VG_(printf)("mkLazy4: I32 x I128 x I128 x I128 -> I128\n");
+ /* Widen 1st arg to I128. Since 1st arg is typically a rounding
+ mode indication which is fully defined, this should get
+ folded out later. */
+ at = mkPCastTo(mce, Ity_I128, va1);
+ /* Now fold in 2nd, 3rd, 4th args. */
+ at = mkUifU(mce, Ity_I128, at, va2);
+ at = mkUifU(mce, Ity_I128, at, va3);
+ at = mkUifU(mce, Ity_I128, at, va4);
+ /* and PCast once again. */
+ at = mkPCastTo(mce, Ity_I128, at);
+ return at;
+ }
+
+ /* I32 x I64 x I64 x I64 -> I64 */
if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64 && t4 == Ity_I64
&& finalVty == Ity_I64) {
if (0) VG_(printf)("mkLazy4: I32 x I64 x I64 x I64 -> I64\n");
@@ -2510,6 +2526,7 @@
case Iop_QNarrowUn32Uto16Ux4:
case Iop_QNarrowUn32Sto16Sx4:
case Iop_QNarrowUn32Sto16Ux4:
+ case Iop_F32toF16x4:
return Iop_NarrowUn32to16x4;
case Iop_QNarrowUn16Uto8Ux8:
case Iop_QNarrowUn16Sto8Sx8:
@@ -2581,6 +2598,7 @@
case Iop_NarrowUn16to8x8:
case Iop_NarrowUn32to16x4:
case Iop_NarrowUn64to32x2:
+ case Iop_F32toF16x4:
at1 = assignNew('V', mce, Ity_I64, unop(narrow_op, vatom1));
return at1;
default:
@@ -2619,6 +2637,7 @@
case Iop_Widen16Sto32x4: pcast = mkPCast32x4; break;
case Iop_Widen32Uto64x2: pcast = mkPCast64x2; break;
case Iop_Widen32Sto64x2: pcast = mkPCast64x2; break;
+ case Iop_F16toF32x4: pcast = mkPCast32x4; break;
default: VG_(tool_panic)("vectorWidenI64");
}
tl_assert(isShadowAtom(mce,vatom1));
@@ -2807,6 +2826,13 @@
/* I32(rm) x F32 x F32 x F32 -> F32 */
return mkLazy4(mce, Ity_I32, vatom1, vatom2, vatom3, vatom4);
+ case Iop_MAddF128:
+ case Iop_MSubF128:
+ case Iop_NegMAddF128:
+ case Iop_NegMSubF128:
+ /* I32(rm) x F128 x F128 x F128 -> F128 */
+ return mkLazy4(mce, Ity_I128, vatom1, vatom2, vatom3, vatom4);
+
/* V256-bit data-steering */
case Iop_64x4toV256:
return assignNew('V', mce, Ity_V256,
@@ -2839,12 +2865,12 @@
tl_assert(sameKindedAtoms(atom3,vatom3));
switch (op) {
case Iop_AddF128:
- case Iop_AddD128:
case Iop_SubF128:
- case Iop_SubD128:
case Iop_MulF128:
- case Iop_MulD128:
case Iop_DivF128:
+ case Iop_AddD128:
+ case Iop_SubD128:
+ case Iop_MulD128:
case Iop_DivD128:
case Iop_QuantizeD128:
/* I32(rm) x F128/D128 x F128/D128 -> F128/D128 */
@@ -3419,6 +3445,8 @@
case Iop_CipherLV128:
case Iop_NCipherV128:
case Iop_NCipherLV128:
+ case Iop_MulI128by10E:
+ case Iop_MulI128by10ECarry:
return binary64Ix2(mce, vatom1, vatom2);
case Iop_QNarrowBin64Sto32Sx4:
@@ -3723,6 +3751,7 @@
case Iop_ShrV128:
case Iop_ShlV128:
+ case Iop_I128StoBCD128:
/* Same scheme as with all other shifts. Note: 10 Nov 05:
this is wrong now, scalar shifts are done properly lazily.
Vector shifts should be fixed too. */
@@ -3862,6 +3891,10 @@
case Iop_D128toI32U: /* IRRoundingMode(I32) x D128 -> unsigned I32 */
return mkLazy2(mce, Ity_I32, vatom1, vatom2);
+ case Iop_F128toI128S: /* IRRoundingMode(I32) x F128 -> signed I128 */
+ case Iop_RndF128: /* IRRoundingMode(I32) x F128 -> F128 */
+ return mkLazy2(mce, Ity_I128, vatom1, vatom2);
+
case Iop_F128toI64S: /* IRRoundingMode(I32) x F128 -> signed I64 */
case Iop_F128toI64U: /* IRRoundingMode(I32) x F128 -> unsigned I64 */
case Iop_F128toF64: /* IRRoundingMode(I32) x F128 -> F64 */
@@ -4373,8 +4406,20 @@
case Iop_NegF128:
case Iop_AbsF128:
+ case Iop_RndF128:
+ case Iop_TruncF128toI64S: /* F128 -> I64S */
+ case Iop_TruncF128toI32S: /* F128 -> I32S (result stored in 64-bits) */
+ case Iop_TruncF128toI64U: /* F128 -> I64U */
+ case Iop_TruncF128toI32U: /* F128 -> I32U (result stored in 64-bits) */
return mkPCastTo(mce, Ity_I128, vatom);
+ case Iop_BCD128toI128S:
+ case Iop_MulI128by10:
+ case Iop_MulI128by10Carry:
+ case Iop_F16toF64x2:
+ case Iop_F64toF16x2:
+ return vatom;
+
case Iop_I32StoF128: /* signed I32 -> F128 */
case Iop_I64StoF128: /* signed I64 -> F128 */
case Iop_I32UtoF128: /* unsigned I32 -> F128 */
@@ -4510,6 +4555,7 @@
case Iop_Clz8x16:
case Iop_Cls8x16:
case Iop_Abs8x16:
+ case Iop_Ctz8x16:
return mkPCast8x16(mce, vatom);
case Iop_CmpNEZ16x4:
@@ -4522,6 +4568,7 @@
case Iop_Clz16x8:
case Iop_Cls16x8:
case Iop_Abs16x8:
+ case Iop_Ctz16x8:
return mkPCast16x8(mce, vatom);
case Iop_CmpNEZ32x2:
@@ -4539,6 +4586,7 @@
case Iop_FtoI32Sx4_RZ:
case Iop_Abs32x4:
case Iop_RSqrtEst32Ux4:
+ case Iop_Ctz32x4:
return mkPCast32x4(mce, vatom);
case Iop_CmpwNEZ32:
@@ -4551,6 +4599,7 @@
case Iop_CipherSV128:
case Iop_Clz64x2:
case Iop_Abs64x2:
+ case Iop_Ctz64x2:
return mkPCast64x2(mce, vatom);
case Iop_PwBitMtxXpose64x2:
@@ -4568,6 +4617,7 @@
case Iop_QNarrowUn64Sto32Sx2:
case Iop_QNarrowUn64Sto32Ux2:
case Iop_QNarrowUn64Uto32Ux2:
+ case Iop_F32toF16x4:
return vectorNarrowUnV128(mce, op, vatom);
case Iop_Widen8Sto16x8:
@@ -4576,6 +4626,7 @@
case Iop_Widen16Uto32x4:
case Iop_Widen32Sto64x2:
case Iop_Widen32Uto64x2:
+ case Iop_F16toF32x4:
return vectorWidenI64(mce, op, vatom);
case Iop_PwAddL32Ux2:
Modified: trunk/memcheck/tests/vbit-test/irops.c
==============================================================================
--- trunk/memcheck/tests/vbit-test/irops.c (original)
+++ trunk/memcheck/tests/vbit-test/irops.c Mon Aug 15 22:54:04 2016
@@ -239,6 +239,10 @@
{ DEFOP(Iop_SubF128, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_MulF128, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_DivF128, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_MAddF128, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_MSubF128, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_NegMAddF128, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_NegMSubF128, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_NegF128, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_AbsF128, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_SqrtF128, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
@@ -252,8 +256,14 @@
{ DEFOP(Iop_F128toI64S, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_F128toI32U, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_F128toI64U, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_F128toI128S, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_F128toF64, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_F128toF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_RndF128, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_TruncF128toI32S,UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_TruncF128toI32U,UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_TruncF128toI64U,UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_TruncF128toI64S,UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_AtanF64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_Yl2xF64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_Yl2xp1F64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
@@ -625,6 +635,8 @@
{ DEFOP(Iop_Fixed32SToF32x4_RN, UNDEF_UNKNOWN), },
{ DEFOP(Iop_F32toF16x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_F16toF32x4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_F64toF16x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_F16toF64x2, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Add32F0x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Sub32F0x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Mul32F0x4, UNDEF_UNKNOWN), },
@@ -804,6 +816,10 @@
{ DEFOP(Iop_Clz16x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Clz32x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Clz64x2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_Ctz8x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Ctz16x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Ctz32x4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Ctz64x2, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Cls8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Cls16x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Cls32x4, UNDEF_UNKNOWN), },
@@ -980,6 +996,11 @@
{ DEFOP(Iop_GetMSBs8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_RecipEst32Ux4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_RSqrtEst32Ux4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_MulI128by10, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_MulI128by10Carry, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_MulI128by10E, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_MulI128by10ECarry, UNDEF_UNKNOWN), },
+
/* ------------------ 256-bit SIMD Integer. ------------------ */
{ DEFOP(Iop_V256to64_0, UNDEF_UNKNOWN), },
{ DEFOP(Iop_V256to64_1, UNDEF_UNKNOWN), },
@@ -1068,6 +1089,8 @@
{ DEFOP(Iop_Min64Fx4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_BCDAdd, UNDEF_ALL), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_BCDSub, UNDEF_ALL), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_I128StoBCD128, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_BCD128toI128S, UNDEF_UNKNOWN), },
{ DEFOP(Iop_PolynomialMulAdd8x16, UNDEF_ALL_8x16), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_PolynomialMulAdd16x8, UNDEF_ALL_16x8), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_PolynomialMulAdd32x4, UNDEF_ALL_32x4), .ppc64 = 1, .ppc32 = 1 },
@@ -1241,6 +1264,43 @@
}
break;
+ case Iop_MAddF128:
+ case Iop_MSubF128:
+ case Iop_NegMAddF128:
+ case Iop_NegMSubF128:
+ case Iop_F128toI128S:
+ case Iop_RndF128:
+ case Iop_I64UtoF128:
+ case Iop_I64StoF128:
+ case Iop_F64toF128:
+ case Iop_F128toF64:
+ case Iop_F128toF32:
+ case Iop_TruncF128toI32S:
+ case Iop_TruncF128toI32U:
+ case Iop_TruncF128toI64U:
+ case Iop_TruncF128toI64S:
+ case Iop_F16toF32x4:
+ case Iop_F32toF16x4:
+ case Iop_F64toF16x2:
+ case Iop_F16toF64x2:
+ case Iop_MulI128by10:
+ case Iop_MulI128by10Carry:
+ case Iop_MulI128by10E:
+ case Iop_MulI128by10ECarry: {
+ /* IROps require a processor that supports ISA 2.07 (Power 8) or newer */
+ rc = system(MIN_POWER_ISA " 3.0 ");
+ rc /= 256;
+ /* MIN_POWER_ISA returns 0 if underlying HW supports the
+ * specified ISA or newer. Returns 1 if the HW does not support
+ * the specified ISA. Returns 2 on error.
+ */
+ if (rc == 1) return NULL;
+ if (rc > 2) {
+ panic(" ERROR, min_power_isa() return code is invalid.\n");
+ }
+ }
+ break;
+
/* Other */
default:
break;
Modified: trunk/none/tests/ppc64/ppc64_helpers.h
==============================================================================
--- trunk/none/tests/ppc64/ppc64_helpers.h (original)
+++ trunk/none/tests/ppc64/ppc64_helpers.h Mon Aug 15 22:54:04 2016
@@ -30,6 +30,14 @@
#define AB_DPRINTF(fmt, args...) do { } while (0)
#endif
+/* Exhaustive tests?
+ * Due to the excessive size of the test results, allow a #ifdef to
+ * enable/disable most of the input values.
+ * Off by default.
+ */
+// #define EXHAUSTIVE_TESTS 1
+
+
#define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
#define SET_CR(_arg) \
@@ -183,29 +191,29 @@
/* Extract one CR field */
static int extract_cr_rn(unsigned long local_cr,unsigned long rn) {
- unsigned int masked_cr;
- unsigned long shifted_value;
+ unsigned int masked_cr;
+ unsigned long shifted_value;
- shifted_value = local_cr >> ( ( (7 - rn) * 4 ) );
- masked_cr = shifted_value & 0xf;
- return masked_cr;
+ shifted_value = local_cr >> ( ( (7 - rn) * 4 ) );
+ masked_cr = shifted_value & 0xf;
+ return masked_cr;
}
/* Display one CR field */
static void dissect_cr_rn(unsigned long local_cr, unsigned long rn) {
- unsigned int masked_cr;
+ unsigned int masked_cr;
- masked_cr = extract_cr_rn(local_cr, rn);
- __dissect_cr(masked_cr);
+ masked_cr = extract_cr_rn(local_cr, rn);
+ __dissect_cr(masked_cr);
}
/* Display all of the CR fields... */
static void dissect_cr(unsigned long local_cr) {
- unsigned int crn;
+ unsigned int crn;
- for (crn = 0; crn < 8; crn++) {
- dissect_cr_rn(local_cr, crn);
- }
+ for (crn = 0; crn < 8; crn++) {
+ dissect_cr_rn(local_cr, crn);
+ }
}
/* dissect the fpscr bits that are valid under valgrind.
@@ -422,6 +430,7 @@
*/
static unsigned long dfp128_vals[] = {
+#ifdef EXHAUSTIVE_TESTS
// Some finite numbers
0x2208000000000000ULL, 0x0000000000000001ULL, // 1 *10^0
0xa208800000000000ULL, 0x0000000000000001ULL, // -1 *10^1
@@ -457,13 +466,21 @@
// flavors of NAN
0x7c00000000000000ULL, 0x0000000000000000ULL, // quiet
- 0xfc00000000000000ULL, 0xc00100035b007700ULL,
- 0x7e00000000000000ULL, 0xfe000000d0e0a0d0ULL, // signaling
+ 0xfc00000000000000ULL, 0xc00100035b007700ULL, // NAN
+ 0x7e00000000000000ULL, 0xfe000000d0e0a0d0ULL, // signaling NAN
// flavors of Infinity
0x7800000000000000ULL, 0x0000000000000000ULL, // +inf
0xf800000000000000ULL, 0x0000000000000000ULL, // -inf
0xf900000000000000ULL, 0x0000000000000000ULL // -inf
+#else
+ 0x2208000000000000ULL, 0x0000000000000001ULL, // 1 *10^0
+ 0x77ffffffffffffffULL, 0xffffffffffffffffULL, // max possible value *10^6111 (largest exp)
+ 0xa208000000000000ULL, 0x0000000000000000ULL, // -0*10^0
+ 0xfc00000000000000ULL, 0xc00100035b007700ULL, // NAN
+ 0x7e00000000000000ULL, 0xfe000000d0e0a0d0ULL, // signaling NAN
+ 0xf800000000000000ULL, 0x0000000000000000ULL, // -inf
+#endif
};
#define NUM_DFP128_VALS (sizeof(dfp128_vals) / 8)
@@ -472,7 +489,7 @@
/* Todo: update dfp64_vals to match dfp128_vals content. */
static unsigned long dfp64_vals[] = {
- //
+#ifdef EXHAUSTIVE_TESTS
0x77fcffffffffffffULL, // max possible value 9..9 *10^369 (largest exp)
0x0000000000000001ULL, // min possible nonzero value 1 *10^-398. (smallest exp)
0x4248000000000001ULL, // 1*10^260
@@ -498,6 +515,12 @@
0x7800000000000000ULL, //+Inf
0xf800000000000000ULL, //-Inf
0x7a34000000000000ULL, //+Inf
+#else
+ 0x77fcffffffffffffULL, // max possible value 9..9 *10^369 (largest exp)
+ 0x4248000000000000ULL, // 0 * 10 ^260
+ 0xfe000000d0e0a0d0ULL, //signaling NaN
+ 0xf800000000000000ULL, //-Inf
+#endif
};
#define NUM_DFP64_VALS (sizeof(dfp64_vals) / 8)
@@ -1348,21 +1371,33 @@
/* a table of exponent values for use in the float precision tests. */
unsigned long exponent_table[] = {
+#ifdef EXHAUSTIVE_TESTS
0x0000, /* +/-0 or +/-DENormalized, depending on associated mantissa. */
0x1a, /* within NORmalized for 16,32,64,128-bit. */
0x1f, /* +/-INF or +/-NaN for 16bit, NORmalized for 32,64,128 */
0xff, /* +/-INF or +/-NaN for 32bit, NORmalized for 64,128 */
0x7ff, /* +/-INF or +/-NaN for 32 and 64bit, NORmalized for 128 */
0x7fff, /* +/-INF or +/-NaN for 128bit. */
-#define MAX_EXPONENTS 6
+#else
+ 0x0000, /* +/-0 or +/-DENormalized, depending on associated mantissa. */
+ 0xff, /* +/-INF or +/-NaN for 32bit, NORmalized for 64,128 */
+ 0x7ff, /* +/-INF or +/-NaN for 32 and 64bit, NORmalized for 128 */
+ 0x7fff, /* +/-INF or +/-NaN for 128bit. */
+#endif
};
+#define MAX_EXPONENTS (sizeof(exponent_table) / sizeof(unsigned long))
unsigned long mantissa_table[] = {
+#ifdef EXHAUSTIVE_TESTS
0xbeefbeefbeef, /* NOR or DEN or NaN */
0x000000000000, /* ZERO or INF */
0x7fffffffffff, /* NOR or DEN or NaN */
-#define MAX_MANTISSAS 3
+#else
+ 0x000000000000, /* ZERO or INF */
+ 0x7fffffffffff, /* NOR or DEN or NaN */
+#endif
};
+#define MAX_MANTISSAS (sizeof(mantissa_table) / sizeof(unsigned long))
/* build in 64-bit chunks, low doubleword is zero. */
static unsigned long * float_vsxargs;
@@ -1522,9 +1557,15 @@
char_args = memalign(32, MAX_CHAR_ARGS_ARRAY_SIZE * sizeof(char));
+#ifdef EXHAUSTIVE_TESTS
for (ichar = 'a'; ichar <= 'z'; ichar++) { char_args[i++] = ichar; }
for (ichar = '0'; ichar <= '9'; ichar++) { char_args[i++] = ichar; }
for (ichar = 'A'; ichar <= 'Z'; ichar++) { char_args[i++] = ichar; }
+#else
+ for (ichar = 'a'; ichar <= 'z'; ichar+=6) { char_args[i++] = ichar; }
+ for (ichar = '0'; ichar <= '9'; ichar+=6) { char_args[i++] = ichar; }
+ for (ichar = 'A'; ichar <= 'Z'; ichar+=6) { char_args[i++] = ichar; }
+#endif
char_args[i++] = ' ';
char_args[i++] = '+';
@@ -1645,7 +1686,7 @@
// Permutes work against two (non-paired) VSX regs, so these are
// also grouped by twos.
vsxargs = memalign(16, MAX_VSX_ARRAY_SIZE * sizeof(unsigned long));
-
+#ifdef EXHAUSTIVE_TESTS
vsxargs[i++] = 0x0000000000000000UL; vsxargs[i++] = 0x0000000000000000UL;
vsxargs[i++] = 0x0102030405060708UL; vsxargs[i++] = 0x0102010201020102UL;
@@ -1663,6 +1704,13 @@
vsxargs[i++] = 0x0011223344556677UL; vsxargs[i++] = 0x8899aabbccddeeffUL;
vsxargs[i++] = 0xf0e0d0c0b0a09080UL; vsxargs[i++] = 0x7060504030201000UL;
+#else
+ vsxargs[i++] = 0x0000000000000000UL; vsxargs[i++] = 0x0000000000000000UL;
+ vsxargs[i++] = 0x0102030405060708UL; vsxargs[i++] = 0x0102010201020102UL;
+
+ vsxargs[i++] = 0x0011223344556677UL; vsxargs[i++] = 0x8899aabbccddeeffUL;
+ vsxargs[i++] = 0xf0e0d0c0b0a09080UL; vsxargs[i++] = 0x7060504030201000UL;
+#endif
// these next three groups are specific for vector rotate tests.
// bits 11:15,19:23,27:31 of each 32-bit word contain mb,me,sh values.
@@ -1693,12 +1741,16 @@
vpcv = memalign(16, MAX_VPCV_SIZE * sizeof(unsigned long));
+#ifdef EXHAUSTIVE_TESTS
/* These two lines are complementary pairs of each other. */
vpcv[i++]=0x12021a0817141317ULL; vpcv[i++]=0x100d1b05070f0205ULL;
vpcv[i++]=0x0d1d0517080b0c08ULL; vpcv[i++]=0x0f12041a18101d1cULL;
vpcv[i++]=0x100d1b070f020505ULL; vpcv[i++]=0x0e201f1400130105ULL;
vpcv[i++]=0x0705030a0b01ea0cULL; vpcv[i++]=0x0e0c09010602080dULL;
-
+#else
+ vpcv[i++]=0x12021a0817141317ULL; vpcv[i++]=0x100d1b05070f0205ULL;
+ vpcv[i++]=0x0705030a0b01ea0cULL; vpcv[i++]=0x0e0c09010602080dULL;
+#endif
nb_vpcv=i;
AB_DPRINTF("Registered %d permute control vectors \n", nb_vpcv);
@@ -1791,9 +1843,11 @@
{
long sign_index;
long sign_value;
- int scramble;
unsigned long i = 0;
unsigned long value;
+ #ifdef EXHAUSTIVE_TESTS
+ int scramble;
+#endif
if (verbose) printf("%s\n", __FUNCTION__);
@@ -1814,6 +1868,7 @@
i+=2;
}
+#ifdef EXHAUSTIVE_TESTS
for (scramble = 1; scramble <= 4; scramble++) {
packed_decimal_table[i] = 0x3210321032103210 * scramble;
packed_decimal_table[i+1] = sign_value;
@@ -1824,6 +1879,7 @@
if (verbose>3) printf("\n");
i+=2;
}
+#endif
/* Add some entries that will provide interesting output from
* the convert TO tests.
@@ -1839,6 +1895,7 @@
i += 2;
+#ifdef EXHAUSTIVE_TESTS
packed_decimal_table[i] = 0x0000000000000000;
packed_decimal_table[i+1] = sign_value;
packed_decimal_table[i+1] += 0x0000000098765430;
@@ -1860,6 +1917,7 @@
if (verbose>3) printf("\n");
i += 2;
+#endif
packed_decimal_table[i] = 0x0030000000000000;
packed_decimal_table[i+1] = sign_value;
@@ -1910,11 +1968,16 @@
#define NR_NATIONAL_DECIMAL_SIGNS 2
unsigned int national_decimal_values[] = {
+#ifdef EXHAUSTIVE_TESTS
0x0030, 0x0031, 0x0032, 0x0033, 0x0034,
0x0035, 0x0036, 0x0037, 0x0038, 0x0039
+#else
+ 0x0030, 0x0031,
+ 0x0035, 0x0039
+#endif
};
-#define NR_NATIONAL_DECIMAL_VALUES 10
+#define NR_NATIONAL_DECIMAL_VALUES (sizeof(national_decimal_values) / sizeof(unsigned int))
static unsigned long * national_decimal_table;
@@ -2003,6 +2066,7 @@
}
i += 2;
}
+#ifdef EXHAUSTIVE_TESTS
{ /* a few more for fun */
national_decimal_table[i] = 0x0031003200330034;
national_decimal_table[i+1] = 0x0035003600370000;
@@ -2026,6 +2090,7 @@
}
i += 2;
}
+#endif
}
if (verbose > 2) printf("\n");
@@ -2174,22 +2239,36 @@
printf(" ]");
}
-// Randomly chosen coverage for k includes values: 0,2,4,7,9
-#define SELECTIVE_INCREMENT_ZONED(k) \
+#ifdef EXHAUSTIVE_TESTS
+// Randomly chosen exhaustive coverage for k includes values: 0,2,4,7,9
+# define SELECTIVE_INCREMENT_ZONED(k) \
if (k == 7) k = 9; \
else if (k == 4) k = 7; \
else if (k == 2) k = 4; \
else if (k == 0) k = 2; \
else k++;
-
-// Randomly chosen coverage for signs includes values: 0,1,4,a,b,f
-#define SELECTIVE_INCREMENT_SIGNS(signs) \
+// Randomly chosen exhaustive coverage for signs includes values: 0,1,4,a,b,f
+# define SELECTIVE_INCREMENT_SIGNS(signs) \
if (signs == 0x0) signs = 0x1; \
else if (signs == 0x1) signs = 0x4; \
else if (signs == 0x4) signs = 0xa; \
else if (signs == 0xa) signs = 0xb; \
else if (signs == 0xb) signs = 0xf; \
else signs++;
+#else
+// Randomly chosen coverage for k includes values: 0,7,9
+# define SELECTIVE_INCREMENT_ZONED(k) \
+ if (k == 7) k = 9; \
+ else if (k == 0) k = 7; \
+ else k++;
+// Randomly chosen coverage for signs includes values: 0,4,b,f
+# define SELECTIVE_INCREMENT_SIGNS(signs) \
+ if (signs == 0x0) signs = 0x4; \
+ else if (signs == 0x4) signs = 0xb; \
+ else if (signs == 0xb) signs = 0xf; \
+ else signs++;
+#endif
+
static void build_zoned_decimal_table(void)
{
Modified: trunk/none/tests/ppc64/test_isa_3_0.c
==============================================================================
--- trunk/none/tests/ppc64/test_isa_3_0.c (original)
+++ trunk/none/tests/ppc64/test_isa_3_0.c Mon Aug 15 22:54:04 2016
@@ -224,6 +224,34 @@
PPC_XER_CA = 0x02000000,
};
+static void test_cnttzw (void)
+{
+ __asm__ __volatile__ ("cnttzw 17, 14");
+}
+
+static void test_cnttzd (void)
+{
+ __asm__ __volatile__ ("cnttzd 17, 14");
+}
+
+static void test_dotted_cnttzw (void)
+{
+ __asm__ __volatile__ ("cnttzw. 17, 14");
+}
+
+static void test_dotted_cnttzd (void)
+{
+ __asm__ __volatile__ ("cnttzd. 17, 14");
+}
+
+static test_list_t testgroup_logical_one[] = {
+ { &test_cnttzw , "cnttzw" },
+ { &test_cnttzd , "cnttzd" },
+ { &test_dotted_cnttzw, "cnttzw." },
+ { &test_dotted_cnttzd, "cnttzd." },
+ { NULL , NULL },
+};
+
static void test_modsw (void)
{
__asm__ __volatile__ ("modsw 17, 14, 15");
@@ -252,6 +280,60 @@
{ NULL , NULL },
};
+static void test_dotted_extswsli (void)
+{
+ switch(x_shift) {
+ case SH_0:
+ __asm__ __volatile__ ("extswsli. %0, %1, %2" : "=r" (r17) : "r" (r14), "i" (SH_0) );
+ break;
+
+ case SH_1:
+ __asm__ __volatile__ ("extswsli. %0, %1, %2" : "=r" (r17) : "r" (r14), "i" (SH_1) );
+ break;
+
+ case SH_2:
+ __asm__ __volatile__ ("extswsli. %0, %1, %2" : "=r" (r17) : "r" (r14), "i" (SH_2) );
+ break;
+
+ case SH_3:
+ __asm__ __volatile__ ("extswsli. %0, %1, %2" : "=r" (r17) : "r" (r14), "i" (SH_3) );
+ break;
+
+ default:
+ printf("Unhandled shift value for extswsli. %d\n", x_shift);
+ }
+}
+
+static void test_extswsli (void)
+{
+ switch(x_shift) {
+ case SH_0:
+ __asm__ __volatile__ ("extswsli %0, %1, %2" : "=r" (r17) : "r" (r14), "i"(SH_0));
+ break;
+
+ case SH_1:
+ __asm__ __volatile__ ("extswsli %0, %1, %2" : "=r" (r17) : "r" (r14), "i"(SH_1));
+ break;
+
+ case SH_2:
+ __asm__ __volatile__ ("extswsli %0, %1, %2" : "=r" (r17) : "r" (r14), "i"(SH_2));
+ break;
+
+ case SH_3:
+ __asm__ __volatile__ ("extswsli %0, %1, %2" : "=r" (r17) : "r" (r14), "i"(SH_3));
+ break;
+
+ default:
+ printf("Unhandled shift value for extswsli %d\n", x_shift);
+ }
+}
+
+static test_list_t testgroup_shifted_one[] = {
+ { &test_extswsli , "extswsli " },
+ { &test_dotted_extswsli, "extswsli." },
+ { NULL , NULL },
+};
+
static void test_maddhd (void)
{
__asm__ __volatile__ ("maddhd 17, 14, 15, 16");
@@ -290,57 +372,6 @@
{ NULL , NULL },
};
-static void test_dotted_extswsli (void)
-{
-#define EXTSWSLI_dotted_SHIFT(SH_X) \
- __asm__ __volatile__ ("extswsli. %0,%1,%2" : "=r" (r17) : "r" (r14), "i" (SH_X) );
- switch(x_shift) {
- case SH_0:
- EXTSWSLI_dotted_SHIFT(SH_0);
- break;
- case SH_1:
- EXTSWSLI_dotted_SHIFT(SH_1);
- break;
- case SH_2:
- EXTSWSLI_dotted_SHIFT(SH_2);
- break;
- case SH_3:
- EXTSWSLI_dotted_SHIFT(SH_3);
- break;
- default:
- printf("Unhandled shift value for extswsli. %d\n",x_shift);
- }
-}
-
-static void test_extswsli (void)
-{
-#define EXTSWSLI_SHIFT(x) \
- __asm__ __volatile__ ("extswsli %0,%1,%2":"=r" (r17):"r" (r14),"i"(x));
-
- switch(x_shift) {
- case SH_0:
- EXTSWSLI_SHIFT(SH_0);
- break;
- case SH_1:
- EXTSWSLI_SHIFT(SH_1);
- break;
- case SH_2:
- EXTSWSLI_SHIFT(SH_2);
- break;
- case SH_3:
- EXTSWSLI_SHIFT(SH_3);
- break;
- default:
- printf("Unhandled shift value for extswsli %d\n",x_shift);
- }
-}
-
-static test_list_t testgroup_shifted_one[] = {
- { &test_extswsli, "extswsli ",},
- { &test_dotted_extswsli, "extswsli.",},
- { NULL, NULL,},
-};
-
static void test_vabsdub(void) {
__asm__ __volatile__ ("vabsdub %0, %1, %2" : "+v" (vec_xt): "v" (vec_xa), "v" (vec_xb));
}
@@ -1031,6 +1062,22 @@
__asm__ __volatile__ ("vprtybq %0, %1" : "=v"(vec_xt) : "v"(vec_xb));
}
+static void test_vctzb(void) {
+ __asm__ __volatile__ ("vctzb %0, %1" : "=v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_vctzh(void) {
+ __asm__ __volatile__ ("vctzh %0, %1" : "=v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_vctzw(void) {
+ __asm__ __volatile__ ("vctzw %0, %1" : "=v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_vctzd(void) {
+ __asm__ __volatile__ ("vctzd %0, %1" : "=v"(vec_xt) : "v"(vec_xb));
+}
+
static test_list_t testgroup_vector_extend_sign[] = {
{ &test_vextsb2w, "vextsb2w" },
{ &test_vextsb2d, "vextsb2d" },
@@ -1042,6 +1089,10 @@
{ &test_vprtybw , "vprtybw " },
{ &test_vprtybd , "vprtybd " },
{ &test_vprtybq , "vprtybq " },
+ { &test_vctzb , "vctzb " },
+ { &test_vctzh , "vctzh " },
+ { &test_vctzw , "vctzw " },
+ { &test_vctzd , "vctzd " },
{ NULL , NULL },
};
@@ -1224,8 +1275,8 @@
{ &test_xststdcqp, "xststdcqp " },
{ &test_xststdcdp, "xststdcdp " },
{ &test_xststdcsp, "xststdcsp " },
- { &test_xvtstdcdp, "xvtstdcdp " },
{ &test_xvtstdcsp, "xvtstdcsp " },
+ { &test_xvtstdcdp, "xvtstdcdp " },
{ NULL , NULL },
};
@@ -1370,6 +1421,18 @@
{ NULL , NULL },
};
+static void test_bcdtrunc_p0(void) {
+ __asm__ __volatile__ ("bcdtrunc. %0, %1, %2, 0": "=v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_bcdtrunc_p1(void) {
+ __asm__ __volatile__ ("bcdtrunc. %0, %1, %2, 1": "=v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_bcdutrunc(void) {
+ __asm__ __volatile__ ("bcdutrunc. %0, %1, %2 ": "=v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
static void test_bcdadd_p0(void) {
__asm__ __volatile__ ("bcdadd. %0, %1, %2, 0" : "=v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
}
@@ -1446,6 +1509,34 @@
__asm__ __volatile__ ("bcdctn. %0, %1 " : "=v"(vec_xt) : "v"(vec_xb));
}
+static void test_vmul10uq(void) {
+ __asm__ __volatile__ ("vmul10uq %0, %1 " : "=v"(vec_xt) : "v"(vec_xa));
+}
+
+static void test_vmul10cuq(void) {
+ __asm__ __volatile__ ("vmul10cuq %0, %1 " : "=v"(vec_xt) : "v"(vec_xa));
+}
+
+static void test_vmul10euq(void) {
+ __asm__ __volatile__ ("vmul10euq %0, %1, %2 " : "=v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_vmul10ecuq(void) {
+ __asm__ __volatile__ ("vmul10ecuq %0, %1, %2 " : "=v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_bcdctsq(void) {
+ __asm__ __volatile__ ("bcdctsq. %0, %1 " : "=v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_bcdcfsq_p0(void) {
+ __asm__ __volatile__ ("bcdcfsq. %0, %1, 0 " : "=v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_bcdcfsq_p1(void) {
+ __asm__ __volatile__ ("bcdcfsq. %0, %1, 1 " : "=v"(vec_xt) : "v"(vec_xb));
+}
+
static test_list_t testgroup_bcd_misc[] = {
{ &test_bcdadd_p0 , "bcdadd. p0" },
{ &test_bcdadd_p1 , "bcdadd. p1" },
@@ -1455,7 +1546,7 @@
{ &test_bcdcfn_p1 , "bcdcfn. p1" },
{ &test_bcdcfz_p0 , "bcdcfz. p0" }, /* The p0, p1 substrings are used later */
{ &test_bcdcfz_p1 , "bcdcfz. p1" }, /* " " */
- { &test_bcdctn , "bcdctn." },
+ { &test_bcdctn , "bcdctn. " },
{ &test_bcdctz_p0 , "bcdctz. p0" }, /* note: p0, p1 substrings are used later */
{ &test_bcdctz_p1 , "bcdctz. p1" }, /* " " */
{ &test_bcdcpsgn , "bcdcpsgn." },
@@ -1466,6 +1557,16 @@
{ &test_bcdus , "bcdus. " },
{ &test_bcdsr_p0 , "bcdsr. p0" },
{ &test_bcdsr_p1 , "bcdsr. p1" },
+ { &test_bcdtrunc_p0 , "bcdtrunc. p0" },
+ { &test_bcdtrunc_p1 , "bcdtrunc. p1" },
+ { &test_bcdutrunc , "bcdutrunc. " },
+ { &test_vmul10uq , "vmul10uq " },
+ { &test_vmul10cuq , "vmul10cuq " },
+ { &test_vmul10euq , "vmul10euq " },
+ { &test_vmul10ecuq , "vmul10ecuq " },
+ { &test_bcdctsq , "bcdctsq." },
+ { &test_bcdcfsq_p0 , "bcdcfsq. p0" },
+ { &test_bcdcfsq_p1 , "bcdcfsq. p1" },
{ NULL , NULL },
};
@@ -1615,15 +1716,72 @@
__asm__ __volatile__ ("xsiexpdp %0, %1, %2 " : "+wa" (vec_xt): "r" (r14), "r" (r15));
}
+static void test_xscvhpdp(void) {
+ __asm__ __volatile__ ("xscvhpdp %x0, %x1 " : "+wa" (vec_xt) : "wa" (vec_xb));
+}
+
+static void test_xscvdphp(void) {
+ __asm__ __volatile__ ("xscvdphp %x0, %x1 " : "+wi" (vec_xt) : "wi" (vec_xb));
+}
+
+static void test_xvcvhpsp(void) {
+ __asm__ __volatile__ ("xvcvhpsp %x0, %x1 " : "+ww" (vec_xt) : "ww" (vec_xb));
+}
+
+static void test_xvcvsphp(void) {
+ __asm__ __volatile__ ("xvcvsphp %x0, %x1 " : "+ww" (vec_xt) : "ww" (vec_xb));
+}
+
static test_list_t testgroup_vector_scalar_two_double[] = {
{ &test_xsiexpdp, "xsiexpdp" },
+ { &test_xscvhpdp, "xscvhpdp" },
+ { &test_xscvdphp, "xscvdphp" },
+ { &test_xvcvhpsp, "xvcvhpsp" },
+ { &test_xvcvsphp, "xvcvsphp" },
{ NULL , NULL },
};
+
static void test_xsabsqp(void) {
__asm__ __volatile__ ("xsabsqp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
}
+static void test_xscvdpqp(void) {
+ __asm__ __volatile__ ("xscvdpqp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvqpdp(void) {
+ __asm__ __volatile__ ("xscvqpdp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvqpdpo(void) {
+ __asm__ __volatile__ ("xscvqpdpo %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvqpsdz(void) {
+ __asm__ __volatile__ ("xscvqpsdz %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvqpswz(void) {
+ __asm__ __volatile__ ("xscvqpswz %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvqpudz(void) {
+ __asm__ __volatile__ ("xscvqpudz %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvqpuwz(void) {
+ __asm__ __volatile__ ("xscvqpuwz %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvsdqp(void) {
+ __asm__ __volatile__ ("xscvsdqp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xscvudqp(void) {
+ __asm__ __volatile__ ("xscvudqp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
static void test_xsxexpqp(void) {
__asm__ __volatile__ ("xsxexpqp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
}
@@ -1640,26 +1798,125 @@
__asm__ __volatile__ ("xsnabsqp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
}
+static void test_xssqrtqp(void) {
+ __asm__ __volatile__ ("xssqrtqp %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
+static void test_xssqrtqpo(void) {
+ __asm__ __volatile__ ("xssqrtqpo %0, %1" : "+v"(vec_xt) : "v"(vec_xb));
+}
+
static test_list_t testgroup_vector_scalar_two_quad[] = {
{ &test_xsabsqp , "xsabsqp " },
+ { &test_xscvdpqp , "xscvdpqp " },
+ { &test_xscvqpdp , "xscvqpdp " },
+ { &test_xscvqpdpo, "xscvqpdpo " },
+ { &test_xscvqpsdz, "xscvqpsdz " },
+ { &test_xscvqpswz, "xscvqpswz " },
+ { &test_xscvqpudz, "xscvqpudz " },
+ { &test_xscvqpuwz, "xscvqpuwz " },
+ { &test_xscvsdqp , "xscvsdqp " },
+ { &test_xscvudqp , "xscvudqp " },
{ &test_xsxexpqp , "xsxexpqp " },
{ &test_xsxsigqp , "xsxsigqp " },
{ &test_xsnegqp , "xsnegqp " },
{ &test_xsnabsqp , "xsnabsqp " },
+ { &test_xssqrtqp , "xssqrtqp " },
+ { &test_xssqrtqpo, "xssqrtqpo " },
{ NULL , NULL },
};
+static void test_xsaddqp(void) {
+ __asm__ __volatile__ ("xsaddqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsaddqpo(void) {
+ __asm__ __volatile__ ("xsaddqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
static void test_xscpsgnqp(void) {
__asm__ __volatile__ ("xscpsgnqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
}
+static void test_xsdivqp(void) {
+ __asm__ __volatile__ ("xsdivqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsdivqpo(void) {
+ __asm__ __volatile__ ("xsdivqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
static void test_xsiexpqp(void) {
__asm__ __volatile__ ("xsiexpqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
}
+static void test_xsmaddqp(void) {
+ __asm__ __volatile__ ("xsmaddqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsmaddqpo(void) {
+ __asm__ __volatile__ ("xsmaddqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsmsubqp(void) {
+ __asm__ __volatile__ ("xsmsubqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsmsubqpo(void) {
+ __asm__ __volatile__ ("xsmsubqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsmulqp(void) {
+ __asm__ __volatile__ ("xsmulqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsmulqpo(void) {
+ __asm__ __volatile__ ("xsmulqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsnmaddqp(void) {
+ __asm__ __volatile__ ("xsnmaddqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsnmaddqpo(void) {
+ __asm__ __volatile__ ("xsnmaddqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsnmsubqp(void) {
+ __asm__ __volatile__ ("xsnmsubqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xsnmsubqpo(void) {
+ __asm__ __volatile__ ("xsnmsubqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xssubqp(void) {
+ __asm__ __volatile__ ("xssubqp %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
+static void test_xssubqpo(void) {
+ __asm__ __volatile__ ("xssubqpo %0, %1, %2" : "+v"(vec_xt) : "v"(vec_xa), "v"(vec_xb));
+}
+
static test_list_t testgroup_vector_three_quad[] = {
+ { &test_xsaddqp , "xsaddqp " },
+ { &test_xsaddqpo , "xsaddqpo " },
{ &test_xscpsgnqp , "xscpsgnqp " },
+ { &test_xsdivqp , "xsdivqp " },
+ { &test_xsdivqpo , "xsdivqpo " },
{ &test_xsiexpqp , "xsiexpqp " },
+ { &test_xsmaddqp , "xsmaddqp " },
+ { &test_xsmaddqpo , "xsmaddqpo " },
+ { &test_xsmsubqp , "xsmsubqp " },
+ { &test_xsmsubqpo , "xsmsubqpo " },
+ { &test_xsmulqp , "xsmulqp " },
+ { &test_xsmulqpo , "xsmulqpo " },
+ { &test_xsnmaddqp , "xsnmaddqp " },
+ { &test_xsnmaddqpo, "xsnmaddqpo " },
+ { &test_xsnmsubqp , "xsnmsubqp " },
+ { &test_xsnmsubqpo, "xsnmsubqpo " },
+ { &test_xssubqp , "xssubqp " },
+ { &test_xssubqpo , "xssubqpo " },
{ NULL , NULL },
};
@@ -1739,6 +1996,79 @@
{ NULL , NULL },
};
+#define XSRQPI(R,RMC) \
+ SET_FPSCR_ZERO \
+ SET_CR_ZERO \
+ __asm__ __volatile__ \
+ ("xsrqpi %1, %0, %2, %3" : "=v"(vec_xt) : "i"(R), "v"(vec_xb), "i"(RMC)); \
+ GET_CR(local_cr); \
+ GET_FPSCR(local_fpscr);
+
+#define XSRQPIX(R,RMC) \
+ SET_FPSCR_ZERO \
+ SET_CR_ZERO \
+ __asm__ __volatile__ \
+ ("xsrqpix %1, %0, %2, %3" : "=v"(vec_xt) : "i"(R), "v"(vec_xb), "i"(RMC));\
+ GET_CR(local_cr); \
+ GET_FPSCR(local_fpscr);
+
+#define XSRQPXP(R,RMC) \
+ SET_FPSCR_ZERO \
+ SET_CR_ZERO \
+ __asm__ __volatile__ \
+ ("xsrqpxp %1, %0, %2, %3" : "=v"(vec_xt) : "i"(R), "v"(vec_xb), "i"(RMC));\
+ GET_CR(local_cr); \
+ GET_FPSCR(local_fpscr);
+
+/* For the scalar round to quad instructions, x_index is used to key into
+ * two fields; x_index bit [2] becomes the one-bit 'R' and x_index bits [0, 1]
+ * becomes the two-bit 'RMC'.
+ */
+static void test_xsrqpi(void) {
+ switch(x_index) {
+ case 0: XSRQPI(0, 0); break;
+ case 1: XSRQPI(0, 1); break;
+ case 2: XSRQPI(0, 2); break;
+ case 3: XSRQPI(0, 3); break;
+ case 4: XSRQPI(1, 0); break;
+ case 5: XSRQPI(1, 1); break;
+ case 6: XSRQPI(1, 2); break;
+ case 7: XSRQPI(1, 3); break;
+ }
+}
+static void test_xsrqpix(void) {
+ switch(x_index) {
+ case 0: XSRQPIX(0, 0); break;
+ case 1: XSRQPIX(0, 1); break;
+ case 2: XSRQPIX(0, 2); break;
+ case 3: XSRQPIX(0, 3); break;
+ case 4: XSRQPIX(1, 0); break;
+ case 5: XSRQPIX(1, 1); break;
+ case 6: XSRQPIX(1, 2); break;
+ case 7: XSRQPIX(1, 3); break;
+ }
+}
+
+static void test_xsrqpxp(void) {
+ switch(x_index) {
+ case 0: XSRQPXP(0, 0); break;
+ case 1: XSRQPXP(0, 1); break;
+ case 2: XSRQPXP(0, 2); break;
+ case 3: XSRQPXP(0, 3); break;
+ case 4: XSRQPXP(1, 0); break;
+ case 5: XSRQPXP(1, 1); break;
+ case 6: XSRQPXP(1, 2); break;
+ case 7: XSRQPXP(1, 3); break;
+ }
+}
+
+static test_list_t testgroup_vector_scalar_rounding_quads[] = {
+ { &test_xsrqpi , "xsrqpi " },
+ { &test_xsrqpix, "xsrqpix" },
+ { &test_xsrqpxp, "xsrqpxp" },
+ { NULL , NULL },
+};
+
/* ###### begin all_tests table. */
@@ -1758,11 +2088,21 @@
PPC_INTEGER | PPC_ARITH | PPC_TWO_ARGS,
},
{
+ testgroup_shifted_one,
+ "ppc one argument plus shift",
+ PPC_MISC | PPC_CR | PPC_TWO_ARGS,
+ },
+ {
testgroup_three_args,
"ppc three parameter ops",
PPC_INTEGER | PPC_ARITH | PPC_THREE_ARGS,
},
{
+ testgroup_logical_one,
+ "ppc count zeros",
+ PPC_INTEGER | PPC_LOGICAL | PPC_ONE_ARG,
+ },
+ {
testgroup_set_boolean,
"ppc set boolean",
PPC_INTEGER | PPC_LOGICAL | PPC_ONE_IMM,
@@ -1805,12 +2145,17 @@
{
testgroup_vector_scalar_compare_quads,
"ppc vector scalar compare exponents quads",
- PPC_ALTIVEC_QUAD | PPC_COMPARE,
+ PPC_ALTIVEC_QUAD | PPC_COMPARE | PPC_COMPARE_ARGS,
+ },
+ {
+ testgroup_vector_scalar_rounding_quads,
+ "ppc vector scalar rounding quads",
+ PPC_ALTIVEC_QUAD | PPC_ROUND,
},
{
testgroup_vsx_xxpermute,
"ppc vector permutes",
- PPC_ALTIVEC | PPC_PERMUTE | PPC_THREE_ARGS,
+ PPC_ALTIVEC | PPC_PERMUTE,
},
{
testgroup_vector_four,
@@ -1848,11 +2193,6 @@
PPC_MISC | PPC_TWO_ARGS,
},
{
- testgroup_shifted_one,
- "ppc one argument plus shift",
- PPC_MISC | PPC_THREE_ARGS,
- },
- {
testgroup_vector_scalar_compare_exp_double,
"ppc vector scalar compare exponents doubles",
PPC_ALTIVEC_DOUBLE | PPC_COMPARE | PPC_COMPARE_ARGS,
@@ -1920,6 +2260,47 @@
}
}
+#define instruction_sets_cr0_to_zero(inst_name) \
+ ( (strncmp(inst_name, "cnttzw.", 7) == 0 ) || \
+ (strncmp(inst_name, "cnttzd.", 7) == 0 ) )
+
+static void testfunction_logical_one (const char* instruction_name,
+ test_func_t func,
+ unsigned int test_flags) {
+ int i;
+ volatile HWord_t res;
+ volatile unsigned int cr;
+
+ VERBOSE_FUNCTION_CALLOUT
+
+ for (i = 0; i < nb_iargs; i++) {
+
+ r14 = iargs[i];
+
+ /* The logical instructions will set CR fields to zero, so
+ * lets start with some non zero content in CR0.
+ */
+ SET_CR0_FIELD(0xF);
+
+ (*func)();
+
+ res = r17;
+ GET_CR(cr);
+
+ printf("%s %016lx => %016lx",
+ instruction_name, (long unsigned)iargs[i], (long unsigned)res);
+
+ if (instruction_sets_cr0_to_zero(instruction_name)
+ && ((cr & 0xF0000000) != 0 )) {
+ /* The dotted version sets the CR0 to 0, verify */
+ printf(" Expected cr0 to be zero, it is (%08x)\n", cr & 0xF0000000);
+ }
+ printf("\n");
+
+ if (verbose) printf("\n");
+ }
+}
+
void testfunction_one_arg_with_shift (const char* instruction_name,
test_func_t test_function,
unsigned int ignore_test_flags)
@@ -2775,6 +3156,41 @@
}
}
+static void testfunction_vector_scalar_rounding_quads (const char* instruction_name,
+ test_func_t test_function,
+ unsigned int ignore_test_flags) {
+ /* Uses global variable x_index */
+ /* For this function, x_index is used as a key into R and RMC values.
+ * Also note, the fpscr.rn value may be used to affect the rounding mode.
+ * that variation is not evaluated here. */
+ int j;
+
+ VERBOSE_FUNCTION_CALLOUT
+
+ for (j = 0; j < nb_float_vsxargs - 1; j++) {
+ for (x_index = 0; x_index < 8; x_index++) {
+ vec_xb[0] = float_vsxargs[j];
+ vec_xb[1] = float_vsxargs[j+1];
+
+ printf("%s %016lx%016lx (R=%x) (RMC=%x) => ",
+ instruction_name,
+ vec_xb[1], vec_xb[0],
+ (x_index & 0x4) >> 2, x_index & 0x3);
+
+ SET_CR_ZERO
+ SET_FPSCR_ZERO
+
+ (*test_function)();
+
+ GET_FPSCR(local_fpscr);
+
+ printf("%016lx%016lx", vec_xt[1], vec_xt[0]);
+ dissect_fpscr(local_fpscr);
+ printf("\n");
+ }
+ }
+}
+
static void testfunction_vector_three_special (const char* instruction_name,
test_func_t test_function,
unsigned int ignore_test_flags){
@@ -3191,18 +3607,19 @@
/* ######## begin grand testing loops. */
typedef struct insn_sel_flags_t_struct {
- int one_arg, two_args, three_args, four_args, cmp_args;
- int arith, logical, compare, popcnt, ldst, insert_extract;
- int integer, floats, p405, altivec, altivec_double, altivec_quad;
- int faltivec, vector, misc, dfp, bcd, no_op, pc_immediate;
- int cr;
+ unsigned int one_arg, two_args, three_args, four_args, cmp_args, ld_args, st_args,
+ one_imed_args;
+ unsigned int arith, logical, compare, popcnt, ldst, insert_extract, permute, round;
+ unsigned int integer, altivec, altivec_quad, altivec_double, dfp, bcd, misc,
+ no_op, pc_immediate;
+ unsigned int cr;
} insn_sel_flags_t;
static void do_tests ( insn_sel_flags_t seln_flags)
{
test_group_t group_function;
test_list_t *tests;
- int nb_args, type, family;
+ unsigned int nb_args, type, family;
int i, j, n;
n = 0;
@@ -3231,7 +3648,10 @@
(nb_args == 2 && !seln_flags.two_args) ||
(nb_args == 3 && !seln_flags.three_args) ||
(nb_args == 4 && !seln_flags.four_args) ||
- (nb_args == 5 && !seln_flags.cmp_args))
+ (nb_args == 5 && !seln_flags.cmp_args) ||
+ (nb_args == 6 && !seln_flags.ld_args) ||
+ (nb_args == 7 && !seln_flags.st_args) ||
+ (nb_args == 8 && !seln_flags.one_imed_args))
continue;
/* Check instruction type */
@@ -3246,15 +3666,21 @@
/* Check instruction family */
family = all_tests[i].flags & PPC_FAMILY_MASK;
- if ((family == PPC_INTEGER && !seln_flags.integer) ||
- (family == PPC_ALTIVEC && !seln_flags.altivec) ||
- (family == PPC_ALTIVEC_DOUBLE && !seln_flags.altivec_double) ||
- (family == PPC_ALTIVEC_QUAD && !seln_flags.altivec_quad) ||
- (family == PPC_DFP && !seln_flags.dfp) ||
- (family == PPC_BCD && !seln_flags.bcd) ||
- (family == PPC_NO_OP && !seln_flags.no_op) ||
- (family == PPC_PC_IMMEDIATE && !seln_flags.pc_immediate) ||
- (family == PPC_MISC && !seln_flags.misc))
+
+ /* do each check each case individually to reduce computation */
+ if (family == PPC_INTEGER && seln_flags.integer == 0) continue;
+ if (family == PPC_ALTIVEC && seln_flags.altivec == 0) continue;
+ if (family == PPC_DFP && seln_flags.dfp == 0) continue;
+ if (family == PPC_BCD && seln_flags.bcd == 0) continue;
+ if (family == PPC_NO_OP && seln_flags.no_op == 0) continue;
+ if (family == PPC_MISC && seln_flags.misc == 0) continue;
+ if (family == PPC_ALTIVEC_DOUBLE && seln_flags.altivec_double == 0)
+ continue;
+
+ if (family == PPC_ALTIVEC_QUAD && seln_flags.altivec_quad == 0)
+ continue;
+
+ if (family == PPC_PC_IMMEDIATE && seln_flags.pc_immediate == 0)
continue;
/* Check flags update */
@@ -3291,6 +3717,10 @@
group_function = &testfunction_set_boolean;
break;
+ case PPC_ONE_ARG:
+ group_function = &testfunction_logical_one;
+ break;
+
default:
printf("ERROR: PPC_LOGICAL, unhandled number of arguments. 0x%08x\n",
nb_args);
@@ -3304,7 +3734,7 @@
default:
printf("ERROR: PPC_INTEGER, unhandled type 0x%08x\n", type);
continue;
- } /* switch (nb_args) */
+ } /* switch (type) */
break;
case PPC_ALTIVEC:
@@ -3409,7 +3839,6 @@
printf("ERROR: PPC_MISC, unhandled number of arguments. 0x%08x\n", nb_args);
continue;
} /* switch(PPC_MISC, nb_args) */
-
break;
case PPC_ALTIVEC_QUAD:
@@ -3430,6 +3859,10 @@
group_function = &testfunction_vector_scalar_compare_quads;
break;
+ case PPC_ROUND:
+ group_function = &testfunction_vector_scalar_rounding_quads;
+ break;
+
default:
printf("ERROR: PPC_ALTIVEC_QUAD, unhandled type. %d\n", type);
continue;
@@ -3456,6 +3889,12 @@
printf("ERROR: PPC_ALTIVEC_DOUBLE, PPC_COMPARE, unhandled number of arguments. 0x%08x\n", nb_args);
continue;
} /* switch(PPC_COMPARE, nb_args) */
+ break;
+
+ default:
+ printf("ERROR: PPC_ALTIVEC_DOUBLE, unhandled type. %d\n", type);
+ continue;
+
} /* switch(type) */
break;
@@ -3537,25 +3976,30 @@
flags.three_args = 1;
flags.four_args = 1;
flags.cmp_args = 1;
+ flags.ld_args = 1;
+ flags.st_args = 1;
+ flags.one_imed_args = 1;
// Type
flags.arith = 1;
flags.logical = 1;
- flags.popcnt = 1;
flags.compare = 1;
flags.ldst = 1;
+ flags.popcnt = 1;
flags.insert_extract = 1;
+ flags.permute = 1;
+ flags.round = 1;
// Family
flags.integer = 0;
- flags.misc = 0;
+ flags.altivec = 0;
+ flags.altivec_double = 0;
+ flags.altivec_quad = 0;
flags.dfp = 0;
flags.bcd = 0;
+ flags.misc = 0;
flags.no_op = 0;
flags.pc_immediate = 0;
- flags.altivec = 0;
- flags.altivec_double = 0;
- flags.altivec_quad = 0;
// Flags
flags.cr = 2;
@@ -3644,6 +4088,9 @@
printf(" three_args = %d\n", flags.three_args);
printf(" four_args = %d\n", flags.four_args);
printf(" cmp_args = %d\n", flags.cmp_args);
+ printf(" load_args = %d\n", flags.ld_args);
+ printf(" store_args = %d\n", flags.st_args);
+ printf(" one_im_args = %d\n", flags.one_imed_args);
printf(" type: \n");
printf(" arith = %d\n", flags.arith);
printf(" logical = %d\n", flags.logical);
@@ -3657,6 +4104,7 @@
printf(" altivec quad = %d\n", flags.altivec_quad);
printf(" DFP = %d\n", flags.dfp);
printf(" BCD = %d\n", flags.bcd);
+ printf(" PC immediate shifted = %d\n", flags.pc_immediate);
printf(" misc = %d\n", flags.misc);
printf(" cr update: \n");
printf(" cr = %d\n", flags.cr);
Modified: trunk/none/tests/ppc64/test_isa_3_0_altivec.stdout.exp
==============================================================================
--- trunk/none/tests/ppc64/test_isa_3_0_altivec.stdout.exp (original)
+++ trunk/none/tests/ppc64/test_isa_3_0_altivec.stdout.exp Mon Aug 15 22:54:04 2016
@@ -2,817 +2,245 @@
Test instruction group [ppc vector absolutes]
vabsdub xa:0000000000000000 0000000000000000 xb:0000000000000000 0000000000000000 => xt:0000000000000000 0000000000000000 (00000000)
vabsdub xa:0000000000000000 0000000000000000 xb:0102030405060708 0102030405060708 => xt:0102030405060708 0102030405060708 (00000000)
-vabsdub xa:0000000000000000 0000000000000000 xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa (00000000)
-vabsdub xa:0000000000000000 0000000000000000 xb:5555555555555555 5555555555555555 => xt:5555555555555555 5555555555555555 (00000000)
-vabsdub xa:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa xb:0000000000000000 0000000000000000 => xt:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa (00000000)
-vabsdub xa:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa xb:0102030405060708 0102030405060708 => xt:a9a8a7a6a5a4a3a2 a9a8a7a6a5a4a3a2 (00000000)
-vabsdub xa:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:0000000000000000 0000000000000000 (00000000)
-vabsdub xa:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa xb:5555555555555555 5555555555555555 => xt:5555555555555555 5555555555555555 (00000000)
-vabsdub xa:0102010201020102 08090a0b0c0d0e0f xb:0000000000000000 0000000000000000 => xt:08090a0b0c0d0e0f 0102010201020102 (00000000)
-vabsdub xa:0102010201020102 08090a0b0c0d0e0f xb:0102030405060708 0102030405060708 => xt:0707070707070707 0000020204040606 (00000000)
-vabsdub xa:0102010201020102 08090a0b0c0d0e0f xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:a2a1a09f9e9d9c9b a9a8a9a8a9a8a9a8 (00000000)
-vabsdub xa:0102010201020102 08090a0b0c0d0e0f xb:5555555555555555 5555555555555555 => xt:4d4c4b4a49484746 5453545354535453 (00000000)
-vabsdub xa:070d111d1e555e70 7ea1a5a7abadb0ba xb:0000000000000000 0000000000000000 => xt:7ea1a5a7abadb0ba 070d111d1e555e70 (00000000)
-vabsdub xa:070d111d1e555e70 7ea1a5a7abadb0ba xb:0102030405060708 0102030405060708 => xt:7d9fa2a3a6a7a9b2 060b0e19194f5768 (00000000)
-vabsdub xa:070d111d1e555e70 7ea1a5a7abadb0ba xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:2c09050301030610 a39d998d8c554c3a (00000000)
-vabsdub xa:070d111d1e555e70 7ea1a5a7abadb0ba xb:5555555555555555 5555555555555555 => xt:294c505256585b65 4e4844383700091b (00000000)
-vabsdub xa:ced0deede5ecef00 00115e7eadbabec0 xb:0000000000000000 0000000000000000 => xt:00115e7eadbabec0 ced0deede5ecef00 (00000000)
-vabsdub xa:ced0deede5ecef00 00115e7eadbabec0 xb:0102030405060708 0102030405060708 => xt:010f5b7aa8b4b7b8 cdcedbe9e0e6e808 (00000000)
-vabsdub xa:ced0deede5ecef00 00115e7eadbabec0 xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:aa994c2c03101416 242634433b4245aa (00000000)
-vabsdub xa:ced0deede5ecef00 00115e7eadbabec0 xb:5555555555555555 5555555555555555 => xt:554409295865696b 797b899890979a55 (00000000)
vabsdub xa:8899aabbccddeeff 0011223344556677 xb:0000000000000000 0000000000000000 => xt:0011223344556677 8899aabbccddeeff (00000000)
vabsdub xa:8899aabbccddeeff 0011223344556677 xb:0102030405060708 0102030405060708 => xt:010f1f2f3f4f5f6f 8797a7b7c7d7e7f7 (00000000)
-vabsdub xa:8899aabbccddeeff 0011223344556677 xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:aa99887766554433 2211001122334455 (00000000)
-vabsdub xa:8899aabbccddeeff 0011223344556677 xb:5555555555555555 5555555555555555 => xt:5544332211001122 33445566778899aa (00000000)
vabsdub xa:0000100800001010 0000100000001002 xb:0000000000000000 0000000000000000 => xt:0000100000001002 0000100800001010 (00000000)
vabsdub xa:0000100800001010 0000100000001002 xb:0102030405060708 0102030405060708 => xt:01020d0405060906 01020d0405060908 (00000000)
-vabsdub xa:0000100800001010 0000100000001002 xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:aaaa9aaaaaaa9aa8 aaaa9aa2aaaa9a9a (00000000)
-vabsdub xa:0000100800001010 0000100000001002 xb:5555555555555555 5555555555555555 => xt:5555455555554553 5555454d55554545 (00000000)
vabsdub xa:00001c0800001c10 00001c0000001c02 xb:0000000000000000 0000000000000000 => xt:00001c0000001c02 00001c0800001c10 (00000000)
vabsdub xa:00001c0800001c10 00001c0000001c02 xb:0102030405060708 0102030405060708 => xt:0102190405061506 0102190405061508 (00000000)
-vabsdub xa:00001c0800001c10 00001c0000001c02 xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:aaaa8eaaaaaa8ea8 aaaa8ea2aaaa8e9a (00000000)
-vabsdub xa:00001c0800001c10 00001c0000001c02 xb:5555555555555555 5555555555555555 => xt:5555395555553953 5555394d55553945 (00000000)
vabsdub xa:00001f0800001f10 00001f0000001f02 xb:0000000000000000 0000000000000000 => xt:00001f0000001f02 00001f0800001f10 (00000000)
vabsdub xa:00001f0800001f10 00001f0000001f02 xb:0102030405060708 0102030405060708 => xt:01021c0405061806 01021c0405061808 (00000000)
-vabsdub xa:00001f0800001f10 00001f0000001f02 xb:aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa => xt:aaaa8baaaaaa8ba8 aaaa8ba2aaaa8b9a (00000000)
-vabsdub xa:00001f0800001f10 00001f0000001f02 xb:5555555555555555 5555555555555555 => xt:5555365555553653 5555364d55553645 (00000000)
vabsduh xa:0000000000000000 0000000000000000 xb:0000000000000000 0000000000000000 => xt:0000000000000000 0000000000000000 (00000000)
vabsduh xa:0000000...
[truncated message content] |
|
From: <sv...@va...> - 2016-08-15 21:53:32
|
Author: carll
Date: Mon Aug 15 22:53:20 2016
New Revision: 3244
Log:
Power PC Add support for ISA 3.0, part 5
Added support for the
cnttz, cnttz., cnttzd, cnttzd., vctzb, vctzh, vctzw,
vctzd, xscvhpdp, xscvdphp, xvcvhpsp, xvcvsphpv,
xsrqpi, xsrqpix, xsrqpxp, xsaddqp, xsaddqpo, xsmulqp,
xsmulqpo, xsmaddqp, xsmaddqpo, xsmsubqp, xsmsubqpo,
xsnmaddqp, xsnmaddqpo, xsnmsubqp, xsnmsubqpo, xssubqp,
xssubqpo, xsdivqp, xsdivqpo, xssqrtqp, xssqrtqpo,
xscvqpuwz, xscvudqp, xscvqpswz, xscvsdqp, xscvqpudz,
xscvqpdp, xscvqpdpo, xscvdpqp, xscvqpsdz, vmul10cuq,
vmul10ecuq, vmul10uq, vmul10euq, bcdctsq, bcdcfsq
instructions.
Most of these instructions required adding a new Iop as they could not
be emulated with existing Iops. In some cases, some of the above instrctions
could be emulated using another instruction from the above list.
Most of the instructions add support for 128-bit instructions. There are a
number of helper functions that check a values for zero, infinity, NaN, etc.
for various sizes. The new 128-bit instructions require a new version of these
existing functions for a 128-bit operand. Rather then adding another size
specific version of these functions, the existing size specific functions were
replaced with a single function that takes the size of operand to be operated
on. There are some additional helper functions that are added to support
the size independent version of these functions.
Note this is the last of the 5 patches required to complete the ISA 3.0
support.
Bugzilla 364948
Modified:
trunk/priv/guest_ppc_toIR.c
trunk/priv/host_ppc_defs.c
trunk/priv/host_ppc_defs.h
trunk/priv/host_ppc_isel.c
trunk/priv/ir_defs.c
trunk/pub/libvex_ir.h
Modified: trunk/priv/guest_ppc_toIR.c
==============================================================================
--- trunk/priv/guest_ppc_toIR.c (original)
+++ trunk/priv/guest_ppc_toIR.c Mon Aug 15 22:53:20 2016
@@ -1506,6 +1506,21 @@
return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
}
+/* Get contents of 128-bit reg guest register */
+static IRExpr* getF128Reg ( UInt archreg )
+{
+ vassert(archreg < 64);
+ return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_F128 );
+}
+
+/* Ditto, but write to a reg instead. */
+static void putF128Reg ( UInt archreg, IRExpr* e )
+{
+ vassert(archreg < 64);
+ vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F128);
+ stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
+}
+
/* Ditto, but write to a reg instead. */
static void putVReg ( UInt archreg, IRExpr* e )
{
@@ -1910,6 +1925,36 @@
stmt( IRStmt_Put(guestCR0offset(cr), e) );
}
+static void putC ( IRExpr* e )
+{
+ /* The assumption is that the value of the Floating-Point Result
+ * Class Descriptor bit (C) is passed in the lower four bits of a
+ * 32 bit value.
+ *
+ * Note, the C and FPCC bits which are fields in the FPSCR
+ * register are stored in their own memory location of
+ * memory. The FPCC bits are in the lower 4 bits. The C bit needs
+ * to be shifted to bit 4 in the memory location that holds C and FPCC.
+ * Note not all of the FPSCR register bits are supported. We are
+ * only writing C bit.
+ */
+ IRExpr* tmp;
+
+ vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
+
+ /* Get the FPCC bit field */
+ tmp = binop( Iop_And32,
+ mkU32( 0xF ),
+ unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) );
+
+ stmt( IRStmt_Put( OFFB_C_FPCC,
+ unop( Iop_32to8,
+ binop( Iop_Or32, tmp,
+ binop( Iop_Shl32,
+ binop( Iop_And32, mkU32( 0x1 ), e ),
+ mkU8( 4 ) ) ) ) ) );
+}
+
static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
{
vassert(cr < 8);
@@ -3394,266 +3439,488 @@
mkexpr( x ), \
mkU64( NONZERO_FRAC_MASK ) )
-// Returns exponent part of a single precision floating point as I32
-static IRExpr * fp_exp_part_sp(IRTemp src)
+#define NONZERO_FRAC_MASK32 0x007fffffULL
+#define FP_FRAC_PART32(x) binop( Iop_And32, \
+ mkexpr( x ), \
+ mkU32( NONZERO_FRAC_MASK32 ) )
+
+// Returns exponent part of floating point src as I32
+static IRExpr * fp_exp_part( IRType size, IRTemp src )
{
- return binop( Iop_And32,
- binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
- mkU32( 0xff ) );
+ IRExpr *shift_by, *mask, *tsrc;
+
+ vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
+ || ( size == Ity_I64 ) );
+
+ if( size == Ity_I16 ) {
+ /* The 16-bit floating point value is in the lower 16-bits
+ * of the 32-bit input value.
+ */
+ tsrc = mkexpr( src );
+ mask = mkU32( 0x1F );
+ shift_by = mkU8( 10 );
+
+ } else if( size == Ity_I32 ) {
+ tsrc = mkexpr( src );
+ mask = mkU32( 0xFF );
+ shift_by = mkU8( 23 );
+
+ } else if( size == Ity_I64 ) {
+ tsrc = unop( Iop_64HIto32, mkexpr( src ) );
+ mask = mkU32( 0x7FF );
+ shift_by = mkU8( 52 - 32 );
+ }
+
+ return binop( Iop_And32, binop( Iop_Shr32, tsrc, shift_by ), mask );
}
-// Returns exponent part of floating point as I32
-static IRExpr * fp_exp_part(IRTemp src, Bool sp)
-{
- IRExpr * exp;
- if (sp)
- return fp_exp_part_sp(src);
+/* The following functions check the floating point value to see if it
+ is zero, infinity, NaN, Normalized, Denormalized.
+*/
+/* 16-bit floating point number is stored in the lower 16-bits of 32-bit value */
+#define I16_EXP_MASK 0x7C00
+#define I16_FRACTION_MASK 0x03FF
+#define I32_EXP_MASK 0x7F800000
+#define I32_FRACTION_MASK 0x007FFFFF
+#define I64_EXP_MASK 0x7FF0000000000000ULL
+#define I64_FRACTION_MASK 0x000FFFFFFFFFFFFFULL
+#define V128_EXP_MASK 0x7FFF000000000000ULL
+#define V128_FRACTION_MASK 0x0000FFFFFFFFFFFFULL /* upper 64-bit fractional mask */
+
+void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask,
+ IRTemp *zero );
+
+void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask,
+ IRTemp *zero ) {
+
+ vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
+ || ( size == Ity_I64 ) || ( size == Ity_V128 ) );
+
+ if( size == Ity_I16 ) {
+ /* The 16-bit floating point value is in the lower 16-bits of
+ the 32-bit input value */
+ *frac_mask = newTemp( Ity_I32 );
+ *exp_mask = newTemp( Ity_I32 );
+ *zero = newTemp( Ity_I32 );
+ assign( *exp_mask, mkU32( I16_EXP_MASK ) );
+ assign( *frac_mask, mkU32( I16_FRACTION_MASK ) );
+ assign( *zero, mkU32( 0 ) );
+
+ } else if( size == Ity_I32 ) {
+ *frac_mask = newTemp( Ity_I32 );
+ *exp_mask = newTemp( Ity_I32 );
+ *zero = newTemp( Ity_I32 );
+ assign( *exp_mask, mkU32( I32_EXP_MASK ) );
+ assign( *frac_mask, mkU32( I32_FRACTION_MASK ) );
+ assign( *zero, mkU32( 0 ) );
+
+ } else if( size == Ity_I64 ) {
+ *frac_mask = newTemp( Ity_I64 );
+ *exp_mask = newTemp( Ity_I64 );
+ *zero = newTemp( Ity_I64 );
+ assign( *exp_mask, mkU64( I64_EXP_MASK ) );
+ assign( *frac_mask, mkU64( I64_FRACTION_MASK ) );
+ assign( *zero, mkU64( 0 ) );
- if (!mode64)
- exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
- mkexpr( src ) ),
- mkU8( 20 ) ), mkU32( 0x7ff ) );
- else
- exp = unop( Iop_64to32,
- binop( Iop_And64,
- binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
- mkU64( 0x7ff ) ) );
- return exp;
+ } else {
+ /* V128 is converted to upper and lower 64 bit values, */
+ /* uses 64-bit operators and temps */
+ *frac_mask = newTemp( Ity_I64 );
+ *exp_mask = newTemp( Ity_I64 );
+ *zero = newTemp( Ity_I64 );
+ assign( *exp_mask, mkU64( V128_EXP_MASK ) );
+ /* upper 64-bit fractional mask */
+ assign( *frac_mask, mkU64( V128_FRACTION_MASK ) );
+ assign( *zero, mkU64( 0 ) );
+ }
}
-static IRExpr * is_Inf_sp(IRTemp src)
+/* Helper function for the various function which check the value of
+ the floating point value.
+*/
+static IRExpr * exponent_compare( IRType size, IRTemp src,
+ IRTemp exp_mask, IRExpr *exp_val )
{
- IRTemp frac_part = newTemp(Ity_I32);
- IRExpr * Inf_exp;
+ IROp opAND, opCmpEQ;
- assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
- Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
- return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
-}
+ if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) {
+ /* The 16-bit floating point value is in the lower 16-bits of
+ the 32-bit input value */
+ opAND = Iop_And32;
+ opCmpEQ = Iop_CmpEQ32;
+
+ } else {
+ opAND = Iop_And64;
+ opCmpEQ = Iop_CmpEQ64;
+ }
+
+ if( size == Ity_V128 ) {
+ return binop( opCmpEQ,
+ binop ( opAND,
+ unop( Iop_V128HIto64, mkexpr( src ) ),
+ mkexpr( exp_mask ) ),
+ exp_val );
+
+ } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) {
+ return binop( opCmpEQ,
+ binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
+ exp_val );
+ } else {
+ /* 64-bit operands */
+ if (mode64) {
+ return binop( opCmpEQ,
+ binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
+ exp_val );
+ } else {
+ /* No support for 64-bit compares in 32-bit mode, need to do upper
+ * and lower parts using 32-bit compare operators.
+ */
+ return
+ mkAND1( binop( Iop_CmpEQ32,
+ binop ( Iop_And32,
+ unop(Iop_64HIto32, mkexpr( src ) ),
+ unop(Iop_64HIto32, mkexpr( exp_mask ) ) ),
+ unop(Iop_64HIto32, exp_val ) ),
+ binop( Iop_CmpEQ32,
+ binop ( Iop_And32,
+ unop(Iop_64to32, mkexpr( src ) ),
+ unop(Iop_64to32, mkexpr( exp_mask ) ) ),
+ unop(Iop_64to32, exp_val ) ) );
+ }
+ }
+}
-// Infinity: exp = 7ff and fraction is zero; s = 0/1
-static IRExpr * is_Inf(IRTemp src, Bool sp)
+static IRExpr *fractional_part_compare( IRType size, IRTemp src,
+ IRTemp frac_mask, IRExpr *zero )
{
- IRExpr * Inf_exp, * hi32, * low32;
- IRTemp frac_part;
+ IROp opAND, opCmpEQ;
- if (sp)
- return is_Inf_sp(src);
+ if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) {
+ /*The 16-bit floating point value is in the lower 16-bits of
+ the 32-bit input value */
+ opAND = Iop_And32;
+ opCmpEQ = Iop_CmpEQ32;
+
+ } else {
+ opAND = Iop_And64;
+ opCmpEQ = Iop_CmpEQ64;
+ }
- frac_part = newTemp(Ity_I64);
- assign( frac_part, FP_FRAC_PART(src) );
- Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) );
- hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
- low32 = unop( Iop_64to32, mkexpr( frac_part ) );
- return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
- mkU32( 0 ) ) );
+ if( size == Ity_V128 ) {
+ /* 128-bit, note we only care if the fractional part is zero so take upper
+ 52-bits of fractional part and lower 64-bits and OR them together and test
+ for zero. This keeps the temp variables and operators all 64-bit.
+ */
+ return binop( opCmpEQ,
+ binop( Iop_Or64,
+ binop( opAND,
+ unop( Iop_V128HIto64, mkexpr( src ) ),
+ mkexpr( frac_mask ) ),
+ unop( Iop_V128to64, mkexpr( src ) ) ),
+ zero );
+
+ } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) {
+ return binop( opCmpEQ,
+ binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ),
+ zero );
+ } else {
+ if (mode64) {
+ return binop( opCmpEQ,
+ binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ),
+ zero );
+ } else {
+ /* No support for 64-bit compares in 32-bit mode, need to do upper
+ * and lower parts using 32-bit compare operators.
+ */
+ return
+ mkAND1( binop( Iop_CmpEQ32,
+ binop ( Iop_And32,
+ unop(Iop_64HIto32, mkexpr( src ) ),
+ unop(Iop_64HIto32, mkexpr( frac_mask ) ) ),
+ mkU32 ( 0 ) ),
+ binop( Iop_CmpEQ32,
+ binop ( Iop_And32,
+ unop(Iop_64to32, mkexpr( src ) ),
+ unop(Iop_64to32, mkexpr( frac_mask ) ) ),
+ mkU32 ( 0 ) ) );
+ }
+ }
}
-/* Quad precision floating point number is infinit:
- * exp is 32767 and fraction is zero; sign = 0/1
- */
-static IRExpr * is_Inf_V128 ( IRTemp src )
+// Infinity: exp has all bits set, and fraction is zero; s = 0/1
+static IRExpr * is_Inf( IRType size, IRTemp src )
{
- IRExpr * frac_part_hi, * frac_part_low, *Inf_exp;
+ IRExpr *max_exp, *zero_frac;
+ IRTemp exp_mask, frac_mask, zero;
- Inf_exp = binop( Iop_CmpEQ64,
- binop( Iop_And64,
- binop( Iop_Shr64,
- unop( Iop_V128HIto64,
- mkexpr( src ) ),
- mkU8( 48 ) ),
- mkU64( 0x7FFF ) ),
- mkU64( 0x7FFF ) );
-
- frac_part_hi = binop( Iop_And64,
- unop( Iop_V128HIto64, mkexpr( src ) ),
- mkU64( 0x0000FFFFFFFFFFFF ) );
- frac_part_low = unop( Iop_V128to64, mkexpr( src ) );
-
- return mkAND1( Inf_exp,
- mkAND1( binop( Iop_CmpEQ64, frac_part_hi, mkU64( 0 ) ),
- binop( Iop_CmpEQ64, frac_part_low, mkU64( 0 ) ) ) );
-}
-
-static IRExpr * is_Zero_sp(IRTemp src)
-{
- IRTemp sign_less_part = newTemp(Ity_I32);
- assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
- return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
+ setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
+
+ /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
+ max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) );
+
+ /* check fractional part is all zeros */
+ zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) );
+
+ return mkAND1( max_exp, zero_frac );
}
// Zero: exp is zero and fraction is zero; s = 0/1
-static IRExpr * is_Zero(IRTemp src, Bool sp)
+static IRExpr * is_Zero( IRType size, IRTemp src )
{
- IRExpr * hi32, * low32;
- IRTemp sign_less_part;
- if (sp)
- return is_Zero_sp(src);
+ IRExpr *zero_exp, *zero_frac;
+ IRTemp exp_mask, frac_mask, zero;
- sign_less_part = newTemp(Ity_I64);
+ setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
- assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
- hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
- low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
- return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
- mkU32( 0 ) );
-}
+ /* check the exponent is all zeros, i.e. (exp AND exp_mask) = zero */
+ zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) );
-/* Quad precision floating point number is Zero:
- exp is zero and fraction is zero; sign = 0/1 */
-static IRExpr * is_Zero_V128 ( IRTemp src )
-{
- IRExpr * hi64, * low64;
+ /* check fractional part is all zeros */
+ zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) );
- hi64 = binop( Iop_And64,
- unop( Iop_V128HIto64, mkexpr( src ) ),
- mkU64( 0x7FFFFFFFFFFFFFFF ) );
- low64 = unop( Iop_V128to64, mkexpr( src ) );
- return binop( Iop_CmpEQ64,
- binop( Iop_Or64, hi64, low64 ),
- mkU64( 0 ) );
+ return mkAND1( zero_exp, zero_frac );
}
-/* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
- * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
- * This function returns an IRExpr value of '1' for any type of NaN.
+/* SNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '1'
+ * QNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '0'
*/
-static IRExpr * is_NaN(IRTemp src)
+static IRExpr * is_NaN( IRType size, IRTemp src )
{
- IRExpr * NaN_exp, * hi32, * low32;
- IRTemp frac_part = newTemp(Ity_I64);
+ IRExpr *max_exp, *not_zero_frac;
+ IRTemp exp_mask, frac_mask, zero;
- assign( frac_part, FP_FRAC_PART(src) );
- hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
- low32 = unop( Iop_64to32, mkexpr( frac_part ) );
- NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
- mkU32( 0x7ff ) );
+ setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
- return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
- mkU32( 0 ) ) );
-}
+ /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
+ max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) );
-/* This function returns an IRExpr value of '1' for any type of NaN.
- The passed 'src' argument is assumed to be Ity_I32. */
-static IRExpr * is_NaN_32(IRTemp src)
-{
-#define NONZERO_FRAC_MASK32 0x007fffffULL
-#define FP_FRAC_PART32(x) binop( Iop_And32, \
- mkexpr( x ), \
- mkU32( NONZERO_FRAC_MASK32 ) )
+ /* check fractional part is not zero */
+ not_zero_frac = unop( Iop_Not1,
+ fractional_part_compare( size, src, frac_mask,
+ mkexpr( zero ) ) );
- IRExpr * frac_part = FP_FRAC_PART32(src);
- IRExpr * exp_part = binop( Iop_And32,
- binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
- mkU32( 0x0ff ) );
- IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
-
- return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
+ return mkAND1( max_exp, not_zero_frac );
}
-/* This function returns an IRExpr value of '1' for any type of NaN.
- * The passed 'src' argument is assumed to be a quad precisiion
- * floating point number stored in an Ity_V128.
- */
-static IRExpr * is_NaN_V128 ( IRTemp src )
+/* Denormalized number has a zero exponent and non zero fraction. */
+static IRExpr * is_Denorm( IRType size, IRTemp src )
{
+ IRExpr *zero_exp, *not_zero_frac;
+ IRTemp exp_mask, frac_mask, zero;
- /* ignore top fractional bit */
-#define NONZERO_FRAC_MASK64Hi 0x0000ffffffffffffULL
-#define EXP_MASK 0x7fff
-
- IRExpr * frac_part_hi = binop( Iop_And64,
- unop( Iop_V128HIto64,
- mkexpr ( src ) ),
- mkU64( NONZERO_FRAC_MASK64Hi ) );
+ setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
- IRExpr * frac_part_lo = unop( Iop_V128to64, mkexpr ( src ) );
+ /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
+ zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) );
- IRExpr * exp_part = binop( Iop_And64,
- binop( Iop_Shr64,
- unop( Iop_V128HIto64,
- mkexpr( src ) ),
- mkU8( 48 ) ),
- mkU64( EXP_MASK ) );
- IRExpr * NaN_exp = binop( Iop_CmpEQ64, exp_part, mkU64( EXP_MASK ) );
+ /* check fractional part is not zero */
+ not_zero_frac = unop( Iop_Not1,
+ fractional_part_compare( size, src, frac_mask,
+ mkexpr( zero ) ) );
- return mkAND1( NaN_exp,
- mkOR1( binop( Iop_CmpNE64, frac_part_hi, mkU64( 0 ) ),
- binop( Iop_CmpNE64, frac_part_lo, mkU64( 0 ) ) ) );
+ return mkAND1( zero_exp, not_zero_frac );
}
-static IRExpr * is_Denorm ( IRType size, IRTemp src )
+/* Normalized number has exponent between 1 and max_exp -1, or in other words
+ the exponent is not zero and not equal to the max exponent value. */
+static IRExpr * is_Norm( IRType size, IRTemp src )
{
- /* Denormalized number has a zero exponent and non zero fraction.
- Takes a 32bit or 64-bit floating point number and returns 1-bit result.
- */
- IROp opAND, opSHR, opCmpEQ, opCmpNE;
- IRExpr *shift_by, *mask1, *mask2;
- IRTemp zero = newTemp( size );
+ IRExpr *not_zero_exp, *not_max_exp;
+ IRTemp exp_mask, zero;
- vassert( ( size == Ity_I32 ) || ( size == Ity_I64 ) );
+ vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
+ || ( size == Ity_I64 ) || ( size == Ity_V128 ) );
- if( size == Ity_I32 ) {
- opAND = Iop_And32;
- opSHR = Iop_Shr32;
- opCmpEQ = Iop_CmpEQ32;
- opCmpNE = Iop_CmpNE32;
- shift_by = mkU8( 23 );
- mask1 = mkU32( 0xFF );
- mask2 = mkU32( 0x007fffff );
- assign( zero , mkU32( 0 ) );
+ if( size == Ity_I16 ) {
+ /* The 16-bit floating point value is in the lower 16-bits of
+ the 32-bit input value */
+ exp_mask = newTemp( Ity_I32 );
+ zero = newTemp( Ity_I32 );
+ assign( exp_mask, mkU32( I16_EXP_MASK ) );
+ assign( zero, mkU32( 0 ) );
+
+ } else if( size == Ity_I32 ) {
+ exp_mask = newTemp( Ity_I32 );
+ zero = newTemp( Ity_I32 );
+ assign( exp_mask, mkU32( I32_EXP_MASK ) );
+ assign( zero, mkU32( 0 ) );
+
+ } else if( size == Ity_I64 ) {
+ exp_mask = newTemp( Ity_I64 );
+ zero = newTemp( Ity_I64 );
+ assign( exp_mask, mkU64( I64_EXP_MASK ) );
+ assign( zero, mkU64( 0 ) );
} else {
- opAND = Iop_And64;
- opSHR = Iop_Shr64;
- opCmpEQ = Iop_CmpEQ64;
- opCmpNE = Iop_CmpNE64;
- shift_by = mkU8( 52 );
- mask1 = mkU64( 0x7FF );
- mask2 = mkU64( 0x000fffffffffffffULL );
+ /* V128 is converted to upper and lower 64 bit values, */
+ /* uses 64-bit operators and temps */
+ exp_mask = newTemp( Ity_I64 );
+ zero = newTemp( Ity_I64 );
+ assign( exp_mask, mkU64( V128_EXP_MASK ) );
assign( zero, mkU64( 0 ) );
}
- IRExpr * exp_part = binop( opAND,
- binop( opSHR,
- mkexpr( src ),
- shift_by ),
- mask1 );
- IRExpr * frac = binop( opAND,
- mkexpr( src ),
- mask2 );
-
- return mkAND1( binop( opCmpEQ, exp_part, mkexpr( zero ) ),
- binop( opCmpNE,
- frac,
- mkexpr( zero ) ) );
+ not_zero_exp = unop( Iop_Not1,
+ exponent_compare( size, src,
+ exp_mask, mkexpr( zero ) ) );
+ not_max_exp = unop( Iop_Not1,
+ exponent_compare( size, src,
+ exp_mask, mkexpr( exp_mask ) ) );
+
+ return mkAND1( not_zero_exp, not_max_exp );
}
-static IRExpr * is_Denorm_V128 ( IRTemp src )
-{
- /* Denormalized number has a zero exponent and non zero fraction.
- * Takes a 128-bit floating point number and returns 1-bit result.
+
+static IRExpr * create_FPCC( IRTemp NaN, IRTemp inf,
+ IRTemp zero, IRTemp norm,
+ IRTemp dnorm, IRTemp pos,
+ IRTemp neg ) {
+ IRExpr *bit0, *bit1, *bit2, *bit3;
+
+ /* If the result is NaN then must force bits 1, 2 and 3 to zero
+ * to get correct result.
*/
- IRExpr * exp_part = binop( Iop_And64,
- binop( Iop_Shr64,
- unop( Iop_V128HIto64,
- mkexpr( src ) ),
- mkU8( 48 ) ),
- mkU64( 0x7FFF ) );
- IRExpr * frac_hi = binop( Iop_And64,
- unop( Iop_V128HIto64, mkexpr( src ) ),
- mkU64( 0x0000ffffffffffffULL ) );
- IRExpr * frac_lo = unop( Iop_V128to64, mkexpr( src ) );
- return mkAND1( binop( Iop_CmpEQ64, exp_part, mkU64( 0 ) ),
- mkOR1( binop( Iop_CmpNE64,
- frac_hi,
- mkU64( 0 ) ),
- binop( Iop_CmpNE64,
- frac_lo,
- mkU64( 0 ) ) ) );
+ bit0 = unop( Iop_1Uto32, mkOR1( mkexpr( NaN ), mkexpr( inf ) ) );
+ bit1 = unop( Iop_1Uto32, mkAND1( mkNOT1( mkexpr( NaN ) ), mkexpr( zero ) ) );
+ bit2 = unop( Iop_1Uto32,
+ mkAND1( mkNOT1( mkexpr( NaN ) ),
+ mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( pos ),
+ mkexpr( dnorm ) ),
+ mkAND1( mkexpr( pos ),
+ mkexpr( norm ) ) ),
+ mkAND1( mkexpr( pos ),
+ mkexpr( inf ) ) ),
+ mkAND1( mkNOT1 ( mkexpr( zero ) ),
+ mkNOT1( mkexpr( NaN ) ) ) ) ) );
+ bit3 = unop( Iop_1Uto32,
+ mkAND1( mkNOT1( mkexpr( NaN ) ),
+ mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( neg ),
+ mkexpr( dnorm ) ),
+ mkAND1( mkexpr( neg ),
+ mkexpr( norm ) ) ),
+ mkAND1( mkexpr( neg ),
+ mkexpr( inf ) ) ),
+ mkAND1( mkNOT1 ( mkexpr( zero ) ),
+ mkNOT1( mkexpr( NaN ) ) ) ) ) );
+
+ return binop( Iop_Or32,
+ binop( Iop_Or32,
+ bit0,
+ binop( Iop_Shl32, bit1, mkU8( 1 ) ) ),
+ binop( Iop_Or32,
+ binop( Iop_Shl32, bit2, mkU8( 2 ) ),
+ binop( Iop_Shl32, bit3, mkU8( 3 ) ) ) );
}
+static IRExpr * create_C( IRTemp NaN, IRTemp zero,
+ IRTemp dnorm, IRTemp pos,
+ IRTemp neg )
+{
+
+ return unop( Iop_1Uto32,
+ mkOR1( mkOR1( mkexpr( NaN ),
+ mkAND1( mkexpr( neg ), mkexpr( dnorm ) ) ),
+ mkOR1( mkAND1( mkexpr( neg ), mkexpr( zero ) ),
+ mkAND1( mkexpr( pos ), mkexpr( dnorm ) ) ) ) );
+}
+
+static void generate_store_FPRF( IRType size, IRTemp src )
+{
+ IRExpr *FPCC, *C;
+ IRTemp NaN = newTemp( Ity_I1 ), inf = newTemp( Ity_I1 );
+ IRTemp dnorm = newTemp( Ity_I1 ), norm = newTemp( Ity_I1 );
+ IRTemp pos = newTemp( Ity_I1 ), neg = newTemp( Ity_I1 );
+ IRTemp zero = newTemp( Ity_I1 );
+
+ IRTemp sign_bit = newTemp( Ity_I1 );
+ IRTemp value;
+
+ vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
+ || ( size == Ity_I64 ) || ( size == Ity_F128 ) );
+
+ vassert( ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I32 )
+ || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I64 )
+ || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_F128 ) );
+
+ if( size == Ity_I16 ) {
+ /* The 16-bit floating point value is in the lower 16-bits of
+ the 32-bit input value */
+ value = newTemp( Ity_I32 );
+ assign( value, mkexpr( src ) );
+ assign( sign_bit,
+ unop ( Iop_32to1,
+ binop( Iop_And32,
+ binop( Iop_Shr32, mkexpr( value ), mkU8( 15 ) ),
+ mkU32( 0x1 ) ) ) );
+
+ } else if( size == Ity_I32 ) {
+ value = newTemp( size );
+ assign( value, mkexpr( src ) );
+ assign( sign_bit,
+ unop ( Iop_32to1,
+ binop( Iop_And32,
+ binop( Iop_Shr32, mkexpr( value ), mkU8( 31 ) ),
+ mkU32( 0x1 ) ) ) );
+
+ } else if( size == Ity_I64 ) {
+ value = newTemp( size );
+ assign( value, mkexpr( src ) );
+ assign( sign_bit,
+ unop ( Iop_64to1,
+ binop( Iop_And64,
+ binop( Iop_Shr64, mkexpr( value ), mkU8( 63 ) ),
+ mkU64( 0x1 ) ) ) );
+
+ } else {
+ /* Move the F128 bit pattern to an integer V128 bit pattern */
+ value = newTemp( Ity_V128 );
+ assign( value,
+ binop( Iop_64HLtoV128,
+ unop( Iop_ReinterpF64asI64,
+ unop( Iop_F128HItoF64, mkexpr( src ) ) ),
+ unop( Iop_ReinterpF64asI64,
+ unop( Iop_F128LOtoF64, mkexpr( src ) ) ) ) );
+
+ size = Ity_V128;
+ assign( sign_bit,
+ unop ( Iop_64to1,
+ binop( Iop_And64,
+ binop( Iop_Shr64,
+ unop( Iop_V128HIto64, mkexpr( value ) ),
+ mkU8( 63 ) ),
+ mkU64( 0x1 ) ) ) );
+ }
+
+ /* Calculate the floating point result field FPRF */
+ assign( NaN, is_NaN( size, value ) );
+ assign( inf, is_Inf( size, value ) );
+ assign( zero, is_Zero( size, value ) );
+ assign( norm, is_Norm( size, value ) );
+ assign( dnorm, is_Denorm( size, value ) );
+ assign( pos, mkAND1( mkNOT1( mkexpr( sign_bit ) ), mkU1( 1 ) ) );
+ assign( neg, mkAND1( mkexpr( sign_bit ), mkU1( 1 ) ) );
+
+ /* create the FPRF bit field
+ *
+ * FPRF field[4:0] type of value
+ * 10001 QNaN
+ * 01001 - infininity
+ * 01000 - Normalized
+ * 11000 - Denormalized
+ * 10010 - zero
+ * 00010 + zero
+ * 10100 + Denormalized
+ * 00100 + Normalized
+ * 00101 + infinity
+ */
+ FPCC = create_FPCC( NaN, inf, zero, norm, dnorm, pos, neg );
+ C = create_C( NaN, zero, dnorm, pos, neg );
+
+ /* Write the C and FPCC fields of the FPRF field */
+ putC( C );
+ putFPCC( FPCC );
+}
/* This function takes an Ity_I32 input argument interpreted
as a single-precision floating point value. If src is a
@@ -3671,7 +3938,7 @@
/* check if input is SNaN, if it is convert to QNaN */
assign( is_SNAN,
- mkAND1( is_NaN_32( tmp ),
+ mkAND1( is_NaN( Ity_I32, tmp ),
binop( Iop_CmpEQ32,
binop( Iop_And32, mkexpr( tmp ),
mkU32( SNAN_MASK32 ) ),
@@ -3711,7 +3978,8 @@
binop( Iop_CmpEQ32,
binop( Iop_Xor32,
mkexpr( signbit_32 ),
- unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
+ unop( Iop_1Uto32, is_NaN( Ity_I64,
+ intermediateResult ) ) ),
mkU32( 1 ) ) ) );
assign( negatedResult,
@@ -3754,7 +4022,8 @@
binop( Iop_CmpEQ32,
binop( Iop_Xor32,
mkexpr( signbit_32 ),
- unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
+ unop( Iop_1Uto32, is_NaN( Ity_I32,
+ intermediateResult ) ) ),
mkU32( 1 ) ) ) );
assign( negatedResult,
@@ -4074,9 +4343,8 @@
static IRExpr * BCDstring_zero (IRExpr *src)
{
- /* The src is a 128-bit value containing a BCD string and a sign in the
- * least significant byte. The function returns a 1 if the BCD string
- * values are all zero, 0 otherwise.
+ /* The src is a 128-bit value containing a BCD string. The function
+ * returns a 1 if the BCD string values are all zero, 0 otherwise.
*/
IRTemp tsrc = newTemp( Ity_V128 );
assign( tsrc, src);
@@ -5207,6 +5475,67 @@
break;
}
+ case 0x21A: // cnttzw, cnttzw. Count Trailing Zero Word
+ {
+ /* Note cnttzw RA, RS - RA is dest, RS is source. But the
+ * order of the operands in theInst is opc1 RS RA opc2 which has
+ * the operand fields backwards to what the standard order.
+ */
+ UChar rA_address = ifieldRegA(theInstr);
+ UChar rS_address = ifieldRegDS(theInstr);
+ IRTemp rA = newTemp(Ity_I64);
+ IRTemp rS = newTemp(Ity_I64);
+ UChar flag_rC = ifieldBIT0(theInstr);
+ IRTemp result = newTemp(Ity_I32);
+
+ DIP("cnttzw%s r%u,r%u\n", flag_rC ? "." : "",
+ rA_address, rS_address);
+
+ assign( rS, getIReg( rS_address ) );
+ assign( result, unop( Iop_Ctz32,
+ unop( Iop_64to32, mkexpr( rS ) ) ) );
+ assign( rA, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( result ) ) );
+
+ if ( flag_rC )
+ set_CR0( mkexpr( rA ) );
+
+ putIReg( rA_address, mkexpr( rA ) );
+
+ return True; /* Return here since this inst is not consistent
+ * with the other instructions
+ */
+ }
+ break;
+
+ case 0x23A: // cnttzd, cnttzd. Count Trailing Zero Double word
+ {
+ /* Note cnttzd RA, RS - RA is dest, RS is source. But the
+ * order of the operands in theInst is opc1 RS RA opc2 which has
+ * the operand order listed backwards to what is standard.
+ */
+ UChar rA_address = ifieldRegA(theInstr);
+ UChar rS_address = ifieldRegDS(theInstr);
+ IRTemp rA = newTemp(Ity_I64);
+ IRTemp rS = newTemp(Ity_I64);
+ UChar flag_rC = ifieldBIT0(theInstr);
+
+ DIP("cnttzd%s r%u,r%u\n", flag_rC ? "." : "",
+ rA_address, rS_address);
+
+ assign( rS, getIReg( rS_address ) );
+ assign( rA, unop( Iop_Ctz64, mkexpr( rS ) ) );
+
+ if ( flag_rC == 1 )
+ set_CR0( mkexpr( rA ) );
+
+ putIReg( rA_address, mkexpr( rA ) );
+
+ return True; /* Return here since this inst is not consistent
+ * with the other instructions
+ */
+ }
+ break;
+
case 0x309: // modsd Modulo Signed Double Word
{
IRTemp rA = newTemp( Ity_I64 );
@@ -9317,6 +9646,31 @@
IRRoundingMode. PPCRoundingMode encoding is different to
IRRoundingMode, so need to map it.
*/
+
+static IRExpr* /* :: Ity_I32 */ set_round_to_Oddmode ( void )
+{
+/* PPC/ valgrind have two-bits to designate the rounding mode.
+ ISA 3.0 adds instructions than can use a round to odd mode
+ but did not change the number of bits for the rm. Basically,
+ they added two instructions that only differ by the rounding
+ mode the operation uses. In essesce, they encoded the rm
+ in the name. In order to avoid having to create Iops, that
+ encode the rm in th name, we will "expand" the definition of
+ the rounding mode bits. We will just pass the rm and then
+ map the to odd mode to the appropriate PPCFpOp name that
+ will tell us which instruction to map to.
+
+ rounding mode | PPC | IR
+ ------------------------
+ to nearest | 000 | 00
+ to zero | 001 | 11
+ to +infinity | 010 | 10
+ to -infinity | 011 | 01
+ to odd | 1xx | xx
+*/
+ return mkU32(8);
+}
+
static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
{
/*
@@ -10134,6 +10488,7 @@
* Otherwise fg_flag is set to 0.
*
*/
+
static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
{
// The following temps are for holding intermediate results
@@ -10147,7 +10502,12 @@
IRTemp frbInf_tmp = newTemp(Ity_I1);
*fe_flag_tmp = newTemp(Ity_I32);
*fg_flag_tmp = newTemp(Ity_I32);
- assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
+
+ if ( sp )
+ assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_Int ) );
+ else
+ assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_Int ) );
+
assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
////////////////// fe_flag tests BEGIN //////////////////////
@@ -10155,9 +10515,17 @@
* (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv()
* for details.)
*/
- frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
- assign( frbInf_tmp, is_Inf(frB_Int, sp) );
- assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
+ if ( sp ) {
+ frbNaN = is_NaN( Ity_I32, frB_Int );
+ assign( frbInf_tmp, is_Inf( Ity_I32, frB_Int ) );
+ assign( frbZero_tmp, is_Zero( Ity_I32, frB_Int ) );
+
+ } else {
+ frbNaN = is_NaN( Ity_I64, frB_Int );
+ assign( frbInf_tmp, is_Inf( Ity_I64, frB_Int ) );
+ assign( frbZero_tmp, is_Zero( Ity_I64, frB_Int ) );
+ }
+
{
// Test_value = -970 for double precision
UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
@@ -10271,8 +10639,14 @@
IRExpr * fe_flag, * fg_flag;
// Create temps that will be used throughout the following tests.
- assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
- assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
+ if ( sp ) {
+ assign( frA_exp_shR, fp_exp_part( Ity_I32, frA_int ) );
+ assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_int ) );
+ } else{
+ assign( frA_exp_shR, fp_exp_part( Ity_I64, frA_int ) );
+ assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_int ) );
+ }
+
/* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
@@ -10285,28 +10659,26 @@
* Test if the double-precision floating-point operand in register FRA is
* a NaN:
*/
- fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
+ fraNaN = sp ? is_NaN( Ity_I32, frA_int ) : is_NaN( Ity_I64, frA_int );
/*
- * Test if the double-precision floating-point operand in register FRA is
- * an Infinity.
+ * Test if the double-precision floating-point operands in register FRA
+ * and FRB is an Infinity. Test if FRB is zero.
*/
- assign(fraInf_tmp, is_Inf(frA_int, sp));
+ if ( sp ) {
+ assign(fraInf_tmp, is_Inf( Ity_I32, frA_int ) );
+ assign( frbInf_tmp, is_Inf( Ity_I32, frB_int ) );
+ assign( frbZero_tmp, is_Zero( Ity_I32, frB_int ) );
+ } else {
+ assign(fraInf_tmp, is_Inf( Ity_I64, frA_int ) );
+ assign( frbInf_tmp, is_Inf( Ity_I64, frB_int ) );
+ assign( frbZero_tmp, is_Zero( Ity_I64, frB_int ) );
+ }
/*
* Test if the double-precision floating-point operand in register FRB is
* a NaN:
*/
- frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
- /*
- * Test if the double-precision floating-point operand in register FRB is
- * an Infinity.
- */
- assign( frbInf_tmp, is_Inf(frB_int, sp) );
- /*
- * Test if the double-precision floating-point operand in register FRB is
- * a Zero.
- */
- assign( frbZero_tmp, is_Zero(frB_int, sp) );
+ frbNaN = sp ? is_NaN( Ity_I32, frB_int ) : is_NaN( Ity_I64, frB_int );
/*
* Test if e_b <= -1022 for double precision;
@@ -10329,7 +10701,11 @@
/*
* Test if FRA != Zero and (e_a - e_b) >= bias
*/
- assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
+ if ( sp )
+ assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I32, frA_int ) ) );
+ else
+ assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I64, frA_int ) ) );
+
ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
binop( Iop_CmpLT32S, mkU32( bias ),
binop( Iop_Sub32, mkexpr( e_a ),
@@ -14723,12 +15099,64 @@
mkexpr( vB ) ) );
break;
+ case 28: // vctzb, Vector Count Trailing Zeros Byte
+ {
+ DIP("vctzb v%d,v%d", rT_addr, vB_addr);
+
+ /* This instruction is only available in the ISA 3.0 */
+ if ( !mode64 || !allow_isa_3_0 ) {
+ vex_printf("\n vctzb instruction not supported on non ISA 3.0 platform\n\n");
+ return False;
+ }
+ assign( vT, unop( Iop_Ctz8x16, mkexpr( vB ) ) );
+ }
+ break;
+
+ case 29: // vctzh, Vector Count Trailing Zeros Halfword
+ {
+ DIP("vctzh v%d,v%d", rT_addr, vB_addr);
+
+ /* This instruction is only available in the ISA 3.0 */
+ if ( !mode64 || !allow_isa_3_0 ) {
+ vex_printf("\n vctzh instruction not supported on non ISA 3.0 platform\n\n");
+ return False;
+ }
+ assign( vT, unop( Iop_Ctz16x8, mkexpr( vB ) ) );
+ }
+ break;
+
+ case 30: // vctzw, Vector Count Trailing Zeros Word
+ {
+ DIP("vctzw v%d,v%d", rT_addr, vB_addr);
+
+ /* This instruction is only available in the ISA 3.0 */
+ if ( !mode64 || !allow_isa_3_0 ) {
+ vex_printf("\n vctzw instruction not supported on non ISA 3.0 platform\n\n");
+ return False;
+ }
+ assign( vT, unop( Iop_Ctz32x4, mkexpr( vB ) ) );
+ }
+ break;
+
+ case 31: // vctzd, Vector Count Trailing Zeros Double word
+ {
+ DIP("vctzd v%d,v%d", rT_addr, vB_addr);
+
+ /* This instruction is only available in the ISA 3.0 */
+ if ( !mode64 || !allow_isa_3_0 ) {
+ vex_printf("\n vctzd instruction not supported on non ISA 3.0 platform\n\n");
+ return False;
+ }
+ assign( vT, unop( Iop_Ctz64x2, mkexpr( vB ) ) );
+ }
+ break;
+
default:
vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n");
return False;
}
- putVReg( rT_addr, mkexpr( vT) );
+ putVReg( rT_addr, mkexpr( vT ) );
return True;
}
@@ -15239,22 +15667,22 @@
assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
assign( res0, unop(Iop_64to32, mkexpr(lo64)) );
- b3_result = IRExpr_ITE(is_NaN_32(b3),
+ b3_result = IRExpr_ITE(is_NaN(Ity_I32, b3),
// then: result is 0x{8|0}80000000
mkU32(un_signed ? 0x00000000 : 0x80000000),
// else: result is from the Iop_QFtoI32{s|u}x4_RZ
mkexpr(res3));
- b2_result = IRExpr_ITE(is_NaN_32(b2),
+ b2_result = IRExpr_ITE(is_NaN(Ity_I32, b2),
// then: result is 0x{8|0}80000000
mkU32(un_signed ? 0x00000000 : 0x80000000),
// else: result is from the Iop_QFtoI32{s|u}x4_RZ
mkexpr(res2));
- b1_result = IRExpr_ITE(is_NaN_32(b1),
+ b1_result = IRExpr_ITE(is_NaN(Ity_I32, b1),
// then: result is 0x{8|0}80000000
mkU32(un_signed ? 0x00000000 : 0x80000000),
// else: result is from the Iop_QFtoI32{s|u}x4_RZ
mkexpr(res1));
- b0_result = IRExpr_ITE(is_NaN_32(b0),
+ b0_result = IRExpr_ITE(is_NaN(Ity_I32, b0),
// then: result is 0x{8|0}80000000
mkU32(un_signed ? 0x00000000 : 0x80000000),
// else: result is from the Iop_QFtoI32{s|u}x4_RZ
@@ -16447,8 +16875,8 @@
IRTemp frA_isQNaN = newTemp(Ity_I1);
IRTemp frB_isQNaN = newTemp(Ity_I1);
- assign( frA_isNaN, is_NaN( frA_I64 ) );
- assign( frB_isNaN, is_NaN( frB_I64 ) );
+ assign( frA_isNaN, is_NaN( Ity_I64, frA_I64 ) );
+ assign( frB_isNaN, is_NaN( Ity_I64, frB_I64 ) );
// If operand is a NAN and bit 12 is '0', then it's an SNaN
assign( frA_isSNaN,
mkAND1( mkexpr(frA_isNaN),
@@ -16540,9 +16968,10 @@
IRTemp anyNaN = newTemp(Ity_I1);
IRTemp frA_isZero = newTemp(Ity_I1);
IRTemp frB_isZero = newTemp(Ity_I1);
- assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
- assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
- assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
+ assign( frA_isZero, is_Zero( Ity_I64, frA_I64 ) );
+ assign( frB_isZero, is_Zero( Ity_I64, frB_I64 ) );
+ assign( anyNaN, mkOR1( is_NaN( Ity_I64, frA_I64 ),
+ is_NaN(Ity_I64, frB_I64 ) ) );
#define MINUS_ZERO 0x8000000000000000ULL
return IRExpr_ITE( /* If both arguments are zero . . . */
@@ -16662,7 +17091,7 @@
#define SNAN_MASK 0x0008000000000000ULL
hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
assign( is_SNAN,
- mkAND1( is_NaN( frB_I64 ),
+ mkAND1( is_NaN( Ity_I64, frB_I64 ),
binop( Iop_CmpEQ32,
binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
mkU32( 0 ) ) ) );
@@ -16707,6 +17136,7 @@
assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
+
if (!redp) {
assign( sqrtHi,
binop( Iop_SqrtF64,
@@ -17696,7 +18126,7 @@
* Miscellaneous VSX Scalar Instructions
*/
static Bool
-dis_vxs_misc( UInt theInstr, UInt opc2 )
+dis_vxs_misc( UInt theInstr, UInt opc2, int allow_isa_3_0 )
{
#define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
/* XX3-Form and XX2-Form */
@@ -17781,8 +18211,8 @@
mkU64( 0x7FFF00000000000 ) ) );
/* exp A or exp B is NaN */
- bit7 = mkOR1( is_NaN_V128( vA ),
- is_NaN_V128( vB ) );
+ bit7 = mkOR1( is_NaN( Ity_V128, vA ),
+ is_NaN( Ity_V128, vB ) );
assign( eq_lt_gt, binop( Iop_Or32,
binop( Iop_Shl32,
@@ -17881,6 +18311,10 @@
case 0x2b6: // xsxexpdp (VSX Scalar Extract Exponent Double-Precision)
// xsxsigdp (VSX Scalar Extract Significand Doulbe-Precision)
+ // xsvhpdp (VSX Scalar Convert Half-Precision format
+ // to Double-Precision format)
+ // xscvdphp (VSX Scalar round & convert Double-precision
+ // format to Half-precision format)
{
IRTemp rT = newTemp( Ity_I64 );
UInt inst_select = IFIELD( theInstr, 16, 5);
@@ -17903,8 +18337,9 @@
/* Value is normal if it isn't infinite, zero or denormalized */
normal = mkNOT1( mkOR1(
- mkOR1( is_NaN( tmp ), is_Inf( tmp, False ) ),
- mkOR1( is_Zero( tmp, False ),
+ mkOR1( is_NaN( Ity_I64, tmp ),
+ is_Inf( Ity_I64, tmp ) ),
+ mkOR1( is_Zero( Ity_I64, tmp ),
is_Denorm( Ity_I64, tmp ) ) ) );
assign( rT, binop( Iop_Or64,
@@ -17914,11 +18349,46 @@
binop( Iop_Shl64,
unop( Iop_1Uto64, normal),
mkU8( 52 ) ) ) );
+ putIReg( XT, mkexpr( rT ) );
+
+ } else if (inst_select == 16) {
+ IRTemp result = newTemp( Ity_V128 );
+ IRTemp value = newTemp( Ity_I64 );
+ /* Note: PPC only coverts the 16-bit value in the upper 64-bits
+ * of the source V128 to a 64-bit value stored in the upper
+ * 64-bits of the V128 result. The contents of the lower 64-bits
+ * is undefined.
+ */
+
+ DIP("xscvhpdp v%d, v%d\n", (UInt)XT, (UInt)XB);
+ assign( result, unop( Iop_F16toF64x2, mkexpr( vB ) ) );
+
+ putVSReg( XT, mkexpr( result ) );
+
+ assign( value, unop( Iop_V128HIto64, mkexpr( result ) ) );
+ generate_store_FPRF( Ity_I64, value );
+ return True;
+
+ } else if (inst_select == 17) { // xscvdphp
+ IRTemp value = newTemp( Ity_I32 );
+ IRTemp result = newTemp( Ity_V128 );
+ /* Note: PPC only coverts the 64-bit value in the upper 64-bits of
+ * the V128 and stores the 16-bit result in the upper word of the
+ * V128 result. The contents of the lower 64-bits is undefined.
+ */
+ DIP("xscvdphp v%d, v%d\n", (UInt)XT, (UInt)XB);
+ assign( result, unop( Iop_F64toF16x2, mkexpr( vB ) ) );
+ assign( value, unop( Iop_64to32, unop( Iop_V128HIto64,
+ mkexpr( result ) ) ) );
+ putVSReg( XT, mkexpr( result ) );
+ generate_store_FPRF( Ity_I32, value );
+ return True;
+
} else {
vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" );
+ vex_printf("inst_select = %d\n", inst_select);
return False;
}
- putIReg( XT, mkexpr(rT));
}
break;
@@ -17952,9 +18422,9 @@
mkU8( 63 ) ),
mkU64( 0 ) ) ) );
- assign( NaN, unop( Iop_1Uto64, is_NaN( vB_hi ) ) );
- assign( inf, unop( Iop_1Uto64, is_Inf( vB_hi, False ) ) );
- assign( zero, unop( Iop_1Uto64, is_Zero( vB_hi, False ) ) );
+ assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_I64, vB_hi ) ) );
+ assign( inf, unop( Iop_1Uto64, is_Inf( Ity_I64, vB_hi ) ) );
+ assign( zero, unop( Iop_1Uto64, is_Zero( Ity_I64, vB_hi ) ) );
if (opc2 == 0x254) {
DIP("xststdcsp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask);
@@ -18254,9 +18724,9 @@
mkU8( 31 ) ),
mkU32( 0 ) ) ) );
- assign( NaN[i], unop( Iop_1Uto32, is_NaN_32( value[i] ) ));
- assign( inf[i], unop( Iop_1Uto32, is_Inf( value[i], True ) ) );
- assign( zero[i], unop( Iop_1Uto32, is_Zero( value[i], True ) ) );
+ assign( NaN[i], unop( Iop_1Uto32, is_NaN( Ity_I32, value[i] ) ));
+ assign( inf[i], unop( Iop_1Uto32, is_Inf( Ity_I32, value[i] ) ) );
+ assign( zero[i], unop( Iop_1Uto32, is_Zero( Ity_I32, value[i] ) ) );
assign( dnorm[i], unop( Iop_1Uto32, is_Denorm( Ity_I32,
value[i] ) ) );
@@ -18384,6 +18854,8 @@
// xxbrw
// xxbrd
// xxbrq
+ // xvcvhpsp (VSX Vector Convert Half-Precision format to Single-Precision format)
+ // xvcvsphp (VSX Vector round and convert Single-Precision format to Half-Precision format)
{
UInt inst_select = IFIELD( theInstr, 16, 5);
@@ -18422,15 +18894,14 @@
mkU64( 0x0 ),
mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
- new_XT[i+1] = newTemp(Ity_V128);
-
/* Value is normal if it isn't infinite, zero or denormalized */
normal[i] = mkNOT1( mkOR1(
- mkOR1( is_NaN( value[i] ),
- is_Inf( value[i], False ) ),
- mkOR1( is_Zero( value[i], False ),
+ mkOR1( is_NaN( Ity_I64, value[i] ),
+ is_Inf( Ity_I64, value[i] ) ),
+ mkOR1( is_Zero( Ity_I64, value[i] ),
is_Denorm( Ity_I64,
value[i] ) ) ) );
+ new_XT[i+1] = newTemp(Ity_V128);
assign( new_XT[i+1],
binop( Iop_OrV128,
@@ -18517,9 +18988,9 @@
/* Value is normal if it isn't infinite, zero or denormalized */
normal[i] = mkNOT1( mkOR1(
- mkOR1( is_NaN_32( value[i] ),
- is_Inf( value[i], True ) ),
- mkOR1( is_Zero( value[i], True ),
+ mkOR1( is_NaN( Ity_I32, value[i] ),
+ is_Inf( Ity_I32, value[i] ) ),
+ mkOR1( is_Zero( Ity_I32, value[i] ),
is_Denorm( Ity_I32,
value[i] ) ) ) );
new_value[i] = newTemp(Ity_I32);
@@ -18643,6 +19114,79 @@
putVSReg( XT, mkexpr( new_xT[4] ) );
+ } else if (inst_select == 24) {
+ // xvcvhpsp, (VSX Vector Convert half-precision format to
+ // Single-precision format)
+ /* only supported on ISA 3.0 and newer */
+ IRTemp result = newTemp( Ity_V128 );
+ IRTemp src = newTemp( Ity_I64 );
+
+ if (!allow_isa_3_0) return False;
+
+ DIP("xvcvhpsp v%d,v%d\n", XT,XB);
+ /* The instruction does not set the C or FPCC fields. The
+ * instruction takes four 16-bit values stored in a 128-bit value
+ * as follows: x V | x V | x V | x V where V is a 16-bit
+ * value and x is an unused 16-bit value. To use Iop_F16toF32x4
+ * the four 16-bit values will be gathered into a single 64 bit
+ * value. The backend will scatter the four 16-bit values back
+ * into a 128-bit operand before issuing the instruction.
+ */
+ /* Gather 16-bit float values from V128 source into new 64-bit
+ * source value for the Iop.
+ */
+ assign( src,
+ unop( Iop_V128to64,
+ binop( Iop_Perm8x16,
+ mkexpr( vB ),
+ binop ( Iop_64HLtoV128,
+ mkU64( 0 ),
+ mkU64( 0x020306070A0B0E0F) ) ) ) );
+
+ assign( result, unop( Iop_F16toF32x4, mkexpr( src ) ) );
+
+ putVSReg( XT, mkexpr( result ) );
+
+ } else if (inst_select == 25) {
+ // xvcvsphp, (VSX Vector round and Convert single-precision
+ // format to half-precision format)
+ /* only supported on ISA 3.0 and newer */
+ IRTemp result = newTemp( Ity_V128 );
+ IRTemp tmp64 = newTemp( Ity_I64 );
+ IRTemp f0 = newTemp( Ity_I64 );
+ IRTemp f1 = newTemp( Ity_I64 );
+ IRTemp f2 = newTemp( Ity_I64 );
+ IRTemp f3 = newTemp( Ity_I64 );
+
+ if (!allow_isa_3_0) return False;
+ DIP("xvcvsphp v%d,v%d\n", XT,XB);
+
+ /* Iop_F32toF16x4 is V128 -> I64, scatter the 16-bit floats in the
+ * I64 result to the V128 register to store.
+ */
+ assign( tmp64, unop( Iop_F32toF16x4, mkexpr( vB ) ) );
+ assign( f0,binop( Iop_And64,
+ mkU64( 0xFFFF ), mkexpr( tmp64 ) ) );
+ assign( f1, binop( Iop_And64,
+ mkU64( 0xFFFF0000 ), mkexpr( tmp64 ) ) );
+ assign( f2, binop( Iop_And64,
+ mkU64( 0xFFFF00000000 ), mkexpr( tmp64 ) ) );
+ assign( f3, binop( Iop_And64,
+ mkU64( 0xFFFF000000000000 ), mkexpr( tmp64 ) ) );
+
+ /* Scater 16-bit float values from returned 64-bit value
+ * of V128 result.
+ */
+ assign( result,
+ binop( Iop_Perm8x16,
+ binop( Iop_64HLtoV128,
+ mkU64( 0 ),
+ mkexpr( tmp64 ) ),
+ binop ( Iop_64HLtoV128,
+ mkU64( 0x0000080900000A0B ),
+ mkU64( 0x00000C0D00000E0F ) ) ) );
+ putVSReg( XT, mkexpr( result ) );
+
} else if ( inst_select == 31 ) {
int i;
int shift_left = 8;
@@ -18741,9 +19285,9 @@
mkU8( 63 ) ),
mkU64( 0 ) ) ) );
- assign( NaN[i], unop( Iop_1Uto64, is_NaN( value[i] ) ) );
- assign( inf[i], unop( Iop_1Uto64, is_Inf( value[i], False ) ) );
- assign( zero[i], unop( Iop_1Uto64, is_Zero( value[i], False ) ) );
+ assign( NaN[i], unop( Iop_1Uto64, is_NaN( Ity_I64, value[i] ) ) );
+ assign( inf[i], unop( Iop_1Uto64, is_Inf( Ity_I64, value[i] ) ) );
+ assign( zero[i], unop( Iop_1Uto64, is_Zero( Ity_I64, value[i] ) ) );
assign( dnorm[i], unop( Iop_1Uto64, is_Denorm( Ity_I64,
value[i] ) ) );
@@ -20390,41 +20934,456 @@
return True;
}
-/* VSX Scalar Quad-Precision instructions */
static Bool
-dis_vx_scalar_quad_precision ( UInt theInstr )
+dis_vx_Scalar_Round_to_quad_integer( UInt theInstr )
{
+ /* The ISA 3.0 instructions supported in this function require
+ * the underlying hardware platform that supports the ISA3.0
+ * instruction set.
+ */
/* XX1-Form */
UChar opc1 = ifieldOPC( theInstr );
- UInt opc2 = ifieldOPClo10( theInstr );
- UChar vT_addr = ifieldRegDS( theInstr ) + 32;
- UChar vA_addr = ifieldRegA( theInstr ) + 32;
- UChar vB_addr = ifieldRegB( theInstr ) + 32;
- IRTemp vA = newTemp( Ity_V128 );
- IRTemp vB = newTemp( Ity_V128 );
- IRTemp vT = newTemp( Ity_V128 );
-
- assign( vB, getVSReg(vB_addr));
+ UInt opc2 = IFIELD( theInstr, 1, 8 );
+ UChar vT_addr = ifieldRegDS( theInstr );
+ UChar vB_addr = ifieldRegB( theInstr );
+ IRTemp vB = newTemp( Ity_F128 );
+ IRTemp vT = newTemp( Ity_F128 );
+ UChar EX = IFIELD( theInstr, 0, 1 );
+ assign( vB, getF128Reg( vB_addr ) );
if (opc1 != 0x3F) {
- vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" );
+ vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" );
return False;
}
-
switch (opc2) {
-
- case 0x064: // xscpsgnqp (VSX Scalar Copy Sign Quad-Precision)
+ case 0x005: // VSX Scalar Round to Quad-Precision Integer [with Inexact]
{
- IRTemp sign_vA = newTemp( Ity_I64 );
- IRTemp vB_hi = newTemp( Ity_I64 );
+ UChar R = IFIELD( theInstr, 16, 1 );
+ UChar RMC = IFIELD( theInstr, 9, 2 );
- DIP("xscpsgnqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
+ /* Store the rm specification bits. Will extract them later when
+ * the isntruction is issued.
+ */
+ IRExpr* rm = mkU...
[truncated message content] |
|
From: <sv...@va...> - 2016-08-15 02:31:36
|
Author: iraisr
Date: Mon Aug 15 03:31:27 2016
New Revision: 15937
Log:
Follow up to r15936.
Kernel allocates another page after fork and we have to
keep aspacemgr's point of view consistent.
n-i-bz
Modified:
trunk/coregrind/m_aspacemgr/aspacemgr-linux.c
trunk/coregrind/m_syswrap/syswrap-solaris.c
trunk/coregrind/pub_core_aspacemgr.h
Modified: trunk/coregrind/m_aspacemgr/aspacemgr-linux.c
==============================================================================
--- trunk/coregrind/m_aspacemgr/aspacemgr-linux.c (original)
+++ trunk/coregrind/m_aspacemgr/aspacemgr-linux.c Mon Aug 15 03:31:27 2016
@@ -4057,6 +4057,51 @@
(*record_gap)(gap_start, Addr_MAX - gap_start + 1);
}
+/* parse_procselfmaps() callbacks do not allow for easy thread safety. */
+static Addr found_addr;
+static SizeT found_size;
+static UInt found_prot;
+
+/* Reports a new mapping into variables above. */
+static void new_segment_found_callback(Addr addr, SizeT len, UInt prot,
+ ULong dev, ULong ino, Off64T offset, const HChar *filename)
+{
+ aspacem_assert(addr <= addr + len - 1);
+
+ Int iLo = find_nsegment_idx(addr);
+ Int iHi = find_nsegment_idx(addr + len - 1);
+ aspacem_assert(iLo <= iHi);
+ aspacem_assert(nsegments[iLo].start <= addr);
+ aspacem_assert(nsegments[iHi].end >= addr + len - 1);
+
+ /* Do not perform any sanity checks. That is done in other places.
+ Just find if a reported mapping is found in aspacemgr's book keeping. */
+ for (Int i = iLo; i <= iHi; i++) {
+ if ((nsegments[i].kind == SkFree) || (nsegments[i].kind == SkResvn)) {
+ found_addr = addr;
+ found_size = len;
+ found_prot = prot;
+ break;
+ }
+ }
+}
+
+/* Returns True if a new segment was found. */
+Bool VG_(am_search_for_new_segment)(Addr *addr, SizeT *size, UInt *prot)
+{
+ found_addr = 0;
+ parse_procselfmaps(new_segment_found_callback, NULL);
+
+ if (found_addr != 0) {
+ *addr = found_addr;
+ *size = found_size;
+ *prot = found_prot;
+ return True;
+ } else {
+ return False;
+ }
+}
+
#endif // defined(VGO_solaris)
/*------END-procmaps-parser-for-Solaris--------------------------*/
Modified: trunk/coregrind/m_syswrap/syswrap-solaris.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-solaris.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-solaris.c Mon Aug 15 03:31:27 2016
@@ -6520,6 +6520,27 @@
/* vfork */
if (ARG1 == 2)
VG_(close)(fds[1]);
+
+# if defined(SOLARIS_PT_SUNDWTRACE_THRP)
+ /* Kernel can map a new page as a scratch space of the DTrace fasttrap
+ provider. There is no way we can directly get its address - it's all
+ private to the kernel. Fish it the slow way. */
+ Addr addr;
+ SizeT size;
+ UInt prot;
+ Bool found = VG_(am_search_for_new_segment)(&addr, &size, &prot);
+ if (found) {
+ VG_(debugLog)(1, "syswrap-solaris", "PRE(forksys), new segment: "
+ "vaddr=%#lx, size=%#lx, prot=%#x\n", addr, size, prot);
+ vg_assert(prot == (VKI_PROT_READ | VKI_PROT_EXEC));
+ vg_assert(size == VKI_PAGE_SIZE);
+ ML_(notify_core_and_tool_of_mmap)(addr, size, prot, VKI_MAP_ANONYMOUS,
+ -1, 0);
+
+ /* Note: We don't notify the debuginfo reader about this mapping
+ because there is no debug information stored in this segment. */
+ }
+# endif /* SOLARIS_PT_SUNDWTRACE_THRP */
}
else {
VG_(do_atfork_parent)(tid);
@@ -9345,7 +9366,7 @@
-1, 0);
/* Note: We don't notify the debuginfo reader about this
- mapping because there are no debug information stored in
+ mapping because there is no debug information stored in
this segment. */
}
Modified: trunk/coregrind/pub_core_aspacemgr.h
==============================================================================
--- trunk/coregrind/pub_core_aspacemgr.h (original)
+++ trunk/coregrind/pub_core_aspacemgr.h Mon Aug 15 03:31:27 2016
@@ -378,6 +378,11 @@
Int css_size, /*OUT*/Int* css_used);
#endif
+#if defined(VGO_solaris)
+extern Bool VG_(am_search_for_new_segment)(Addr *start, SizeT *size,
+ UInt *prot);
+#endif
+
#endif // __PUB_CORE_ASPACEMGR_H
/*--------------------------------------------------------------------*/
|