From: Carl Love Date: Tue, 22 Jan 2013 20:26:34 +0000 (+0000) Subject: Fix implementation of the DFP integer operands. X-Git-Tag: svn/VALGRIND_3_9_0~421 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa4ebebbd78624dda6a6df1228472f3f505f82bc;p=thirdparty%2Fvalgrind.git Fix implementation of the DFP integer operands. The implementation of integer operands doesn't really match the documentation for the Iop. Take for example Iop_ExtractExpD64. It is documented as D64 -> I64 but the implementation of the UNARY is defined as UNARY(Ity_D64, Ity_D64). The result is an integer that is stored in an integer format in a floating point register. On the IBM s390 however, the architecture stores the integer value in a general purpose register (GPR) not a floating point register. This issue exists with the implementation of 11 Iops where the PPC implementation has either a source or destination whose value is an integer but the value is stored in a floating point register in an integer format. After reviewing the PPC implementation with the s390 developer, it was agreed the cleanest way to fix this is to change the PPC implementation. The BINOP will be changed to be consistent with the Iop description. This means the PPC instruction implementation of the PPC instruction in guest_ppc_toIR.c will need to reinterpret integer source operands as integers which will move the value from a floating point register to an integer register before calling binop(). The underlying PPC implementation of the unop() for the specific Iop will also need to change to move the value from the integer register back to the floating point register so the native instruction can be issued with the integer value in a floating point register. It was decided that making the changed in PPC, rather then having the s390 reinterpret integers as DFP and then move the value back to an integer register, was preferable as it makes the implementation of the unop(), binops(), triop() consistent with the definition of the Iop. This patch also includes the needed changes for the vbit tester. The Iop definitions in memcheck/tests/vbit-test/util.c had to be updated to be consitent with the changes in the Iops as documented below. Also, the function mkLazy3() in memcheck/mc_translate.c had to be updated to handle the I32 x I8 x I64 -> I64 and I32 x I8 x I128 -> I128 cases. The specific list of changes are as follows: Iop name in pub/libvex_ir.h documented type type of UNARY/BINARY/TERNARY in priv/ir_defs.c ------------------------------------------------------- Iop_ExtractExpD64 D64 -> I64 UNARY(Ity_D64, Ity_D64); (current) UNARY(Ity_D64, Ity_I64); (fix) Iop_ExtractExpD128 D128 -> I64 UNARY(Ity_D128, Ity_D64); (current) UNARY(Ity_D128, Ity_I64); (fix) Iop_InsertExpD64 I64 x I64 -> D64 I64 x D64 -> D64 (fix definition) BINARY(Ity_D64,Ity_D64, Ity_D64); (current) BINARY(Ity_I64,Ity_D64, Ity_D64); (fix) Iop_InsertExpD128 I64 x I128 -> D128 I64 x D128 -> D128 (fix definition) BINARY(Ity_D64,Ity_D128, Ity_D128); (current) BINARY(Ity_I64,Ity_D128, Ity_D128); (fix) Iop_I64StoD128 I64S -> D128 UNARY(Ity_D64, Ity_D128); (current) UNARY(Ity_I64, Ity_D128); (fix) Iop_D64toI64S IRRoundingModeDFP(I32) x D64 -> I64 BINARY(ity_RMode, Ity_D64, Ity_D64) (current) BINARY(ity_RMode, Ity_D64, Ity_I64) (fix) Iop_D128toI64S IRRoundingModeDFP(I32) x D128 -> I64 BINARY(ity_RMode, Ity_D128, Ity_D64); (current) BINARY(ity_RMode, Ity_D128, Ity_I64); (fix) Iop_I64StoD64 IRRoundingModeDFP(I32) x I64 -> D64 BINARY(ity_RMode, Ity_D64, Ity_D64); (current) BINARY(ity_RMode, Ity_I64, Ity_D64); (fix) Iop_SignificanceRoundD64 IRRoundingModeDFP(I32) x I8 x D64 -> D64 TERNARY(ity_RMode,Ity_D64,Ity_D64, Ity_D64); (current) TERNARY(ity_RMode,Ity_I8,Ity_D64, Ity_D64); (fix) Iop_SignificanceRoundD128 IRRoundingModeDFP(I32) x I8 x D128 -> D128 TERNARY(ity_RMode,Ity_D128,Ity_D128, Ity_D128); (current) TERNARY(ity_RMode,Ity_I8,Ity_D128, Ity_D128); (fix) The patch is for bugzilla 311100 VEX Committed revision 2652 git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13260 --- diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c index d93710ce8d..78132cc021 100644 --- a/memcheck/mc_translate.c +++ b/memcheck/mc_translate.c @@ -1570,6 +1570,23 @@ IRAtom* mkLazy3 ( MCEnv* mce, IRType finalVty, return at; } + /* I32 x I8 x I64 -> I64 */ + if (t1 == Ity_I32 && t2 == Ity_I8 && t3 == Ity_I64 + && finalVty == Ity_I64) { + if (0) VG_(printf)("mkLazy3: I32 x I8 x I64 -> I64\n"); + /* Widen 1st and 2nd args to I64. Since 1st arg is typically a + * rounding mode indication which is fully defined, this should + * get folded out later. + */ + IRAtom* at1 = mkPCastTo(mce, Ity_I64, va1); + IRAtom* at2 = mkPCastTo(mce, Ity_I64, va2); + at = mkUifU(mce, Ity_I64, at1, at2); // UifU(PCast(va1), PCast(va2)) + at = mkUifU(mce, Ity_I64, at, va3); + /* and PCast once again. */ + at = mkPCastTo(mce, Ity_I64, at); + return at; + } + /* I32 x I64 x I64 -> I32 */ if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64 && finalVty == Ity_I32) { @@ -1609,6 +1626,24 @@ IRAtom* mkLazy3 ( MCEnv* mce, IRType finalVty, at = mkPCastTo(mce, Ity_I128, at); return at; } + + /* I32 x I8 x I128 -> I128 */ + /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */ + if (t1 == Ity_I32 && t2 == Ity_I8 && t3 == Ity_I128 + && finalVty == Ity_I128) { + if (0) VG_(printf)("mkLazy3: I32 x I8 x I128 -> I128\n"); + /* Widen 1st and 2nd args to I128. Since 1st arg is typically a rounding + mode indication which is fully defined, this should get + folded out later. */ + IRAtom* at1 = mkPCastTo(mce, Ity_I64, va1); + IRAtom* at2 = mkPCastTo(mce, Ity_I64, va2); + /* Now fold in 2nd and 3rd args. */ + at = mkUifU(mce, Ity_I64, at1, at2); // UifU(PCast(va1), PCast(va2)) + at = mkUifU(mce, Ity_I128, at, va3); + /* and PCast once again. */ + at = mkPCastTo(mce, Ity_I128, at); + return at; + } if (1) { VG_(printf)("mkLazy3: "); ppIRType(t1); diff --git a/memcheck/tests/vbit-test/util.c b/memcheck/tests/vbit-test/util.c index 7297f4107f..c893ca6ebd 100644 --- a/memcheck/tests/vbit-test/util.c +++ b/memcheck/tests/vbit-test/util.c @@ -827,22 +827,22 @@ typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, UNARY(Ity_D32, Ity_D64); case Iop_ExtractExpD64: - UNARY(Ity_D64, Ity_D64); + UNARY(Ity_D64, Ity_I64); case Iop_ExtractSigD64: UNARY(Ity_D64, Ity_I64); case Iop_InsertExpD64: - BINARY(Ity_D64,Ity_D64, Ity_D64); + BINARY(Ity_I64,Ity_D64, Ity_D64); case Iop_ExtractExpD128: - UNARY(Ity_D128, Ity_D64); + UNARY(Ity_D128, Ity_I64); case Iop_ExtractSigD128: UNARY(Ity_D128, Ity_I64); case Iop_InsertExpD128: - BINARY(Ity_D64,Ity_D128, Ity_D128); + BINARY(Ity_I64,Ity_D128, Ity_D128); case Iop_D64toD128: UNARY(Ity_D64, Ity_D128); @@ -863,8 +863,8 @@ typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, case Iop_I32UtoD128: UNARY(Ity_I32, Ity_D128); - case Iop_I64StoD128: /* I64 bit pattern stored in Float register */ - UNARY(Ity_D64, Ity_D128); + case Iop_I64StoD128: + UNARY(Ity_I64, Ity_D128); case Iop_I64UtoD128: UNARY(Ity_I64, Ity_D128); @@ -882,7 +882,7 @@ typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, BINARY(ity_RMode, Ity_D128, Ity_I32); case Iop_D128toI64S: - BINARY(ity_RMode, Ity_D128, Ity_D64); + BINARY(ity_RMode, Ity_D128, Ity_I64); case Iop_D128toI64U: BINARY(ity_RMode, Ity_D128, Ity_I64); @@ -894,7 +894,7 @@ typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, case Iop_ShrD64: BINARY(Ity_D64, Ity_I8, Ity_D64 ); - case Iop_D64toD32: + case Iop_D64toD32: BINARY(ity_RMode, Ity_D64, Ity_D32); case Iop_D64toI32S: @@ -902,8 +902,6 @@ typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, BINARY(ity_RMode, Ity_D64, Ity_I32); case Iop_D64toI64S: - BINARY(ity_RMode, Ity_D64, Ity_D64); - case Iop_D64toI64U: BINARY(ity_RMode, Ity_D64, Ity_I64); @@ -911,9 +909,7 @@ typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, case Iop_I32UtoD64: UNARY(Ity_I32, Ity_D64); - case Iop_I64StoD64: /* I64 bit pattern stored in Float register */ - BINARY(ity_RMode, Ity_D64, Ity_D64); - + case Iop_I64StoD64: case Iop_I64UtoD64: BINARY(ity_RMode, Ity_I64, Ity_D64); @@ -926,13 +922,17 @@ typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, BINARY(Ity_D128,Ity_D128, Ity_I32); case Iop_QuantizeD64: - case Iop_SignificanceRoundD64: TERNARY(ity_RMode,Ity_D64,Ity_D64, Ity_D64); + case Iop_SignificanceRoundD64: + TERNARY(ity_RMode,Ity_I8,Ity_D64, Ity_D64); + case Iop_QuantizeD128: - case Iop_SignificanceRoundD128: TERNARY(ity_RMode,Ity_D128,Ity_D128, Ity_D128); + case Iop_SignificanceRoundD128: + TERNARY(ity_RMode,Ity_I8,Ity_D128, Ity_D128); + case Iop_ShlD128: case Iop_ShrD128: BINARY(Ity_D128, Ity_I8, Ity_D128 );