|
[Valgrind-developers] vex: r2277: POWER Processor decimal floating
point instruction support: part 2
From: <sv...@va...> - 2012-04-12 17:20:01
|
sewardj 2012-04-12 18:19:48 +0100 (Thu, 12 Apr 2012)
New Revision: 2277
Log:
POWER Processor decimal floating point instruction support: part 2
(bug #297497) (Carl Love, ca...@us...) (VEX side)
This commit adds the second set of patches to add decimal floating
point (DFP) support for POWER to Valgrind. Bugzilla 295221 contains
the first set of patches for the adding the POWER support for the DFP
32, 64 and 128-bit sizes. The first set of patches also added support
for the 64 and 128-bit DFP arithmetic instructions and user test code
for the new DFP instructions. The second set of patches, being
submitted in this bugzilla include support for the DFP shift
instructions and format conversion instructions. Specifically, the
list of Power instructions is: dctdp, drsp, dctfix, dcffix, dctqpq,
dctfixq, drdpq, dcffixq, dscri, dscriq, dscli, dscliq.
Modified files:
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/pub/libvex_ir.h (+40 -0)
===================================================================
--- trunk/pub/libvex_ir.h 2012-04-11 08:11:28 +01:00 (rev 2276)
+++ trunk/pub/libvex_ir.h 2012-04-12 18:19:48 +01:00 (rev 2277)
@@ -1002,6 +1002,46 @@
*/
Iop_AddD128, Iop_SubD128, Iop_MulD128, Iop_DivD128,
+ /* SHIFT SIGNIFICAND INSTRUCTIONS
+ * The DFP significand is shifted by the number of digits specified
+ * by the U8 operand. Digits shifted out of the leftmost digit are
+ * lost. Zeros are supplied to the vacated positions on the right.
+ * The sign of the result is the same as the sign of the original
+ * operand.
+ */
+ /* D64 x U8 -> D64 left shift and right shift respectively */
+ Iop_ShlD64, Iop_ShrD64,
+
+ /* D128 x U8 -> D128 left shift and right shift respectively */
+ Iop_ShlD128, Iop_ShrD128,
+
+
+ /* FORMAT CONVERSION INSTRUCTIONS
+ * D32 -> D64
+ */
+ Iop_D32toD64,
+
+ /* D64 -> D128 */
+ Iop_D64toD128,
+
+ /* I64S -> D128 */
+ Iop_I64StoD128,
+
+ /* IRRoundingModeDFP(I32) x D64 -> D32 */
+ Iop_D64toD32,
+
+ /* IRRoundingModeDFP(I32) x D128 -> D64 */
+ Iop_D128toD64,
+
+ /* IRRoundingModeDFP(I32) x I64 -> D64 */
+ Iop_I64StoD64,
+
+ /* IRRoundingModeDFP(I32) x D64 -> I64 */
+ Iop_D64toI64S,
+
+ /* IRRoundingModeDFP(I32) x D128 -> I64 */
+ Iop_D128toI64S,
+
/* Support for 128-bit DFP type */
Iop_D64HLtoD128, Iop_D128HItoD64, Iop_D128LOtoD64,
Modified: trunk/priv/guest_ppc_toIR.c (+239 -1)
===================================================================
--- trunk/priv/guest_ppc_toIR.c 2012-04-11 08:11:28 +01:00 (rev 2276)
+++ trunk/priv/guest_ppc_toIR.c 2012-04-12 18:19:48 +01:00 (rev 2277)
@@ -8619,6 +8619,195 @@
return True;
}
+/* DFP 64-bit logical shift instructions */
+static Bool dis_dfp_shift(UInt theInstr) {
+ UInt opc2 = ifieldOPClo9( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frA_addr = ifieldRegA( theInstr );
+ UChar shift_val = IFIELD(theInstr, 10, 6);
+ UChar flag_rC = ifieldBIT0( theInstr );
+
+ IRTemp frA = newTemp( Ity_D64 );
+ IRTemp frS = newTemp( Ity_D64 );
+ Bool clear_CR1 = True;
+
+ assign( frA, getDReg( frA_addr ) );
+
+ switch (opc2) {
+ case 0x42: // dscli
+ DIP( "dscli%s fr%u,fr%u,%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
+ assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
+ break;
+ case 0x62: // dscri
+ DIP( "dscri%s fr%u,fr%u,%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
+ assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
+ break;
+ }
+
+ putDReg( frS_addr, mkexpr( frS ) );
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+/* Quad DFP logical shift instructions */
+static Bool dis_dfp_shiftq(UInt theInstr) {
+ UInt opc2 = ifieldOPClo9( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frA_addr = ifieldRegA( theInstr );
+ UChar shift_val = IFIELD(theInstr, 10, 6);
+ UChar flag_rC = ifieldBIT0( theInstr );
+
+ IRTemp frA = newTemp( Ity_D128 );
+ IRTemp frS = newTemp( Ity_D128 );
+ Bool clear_CR1 = True;
+
+ assign( frA, getDReg_pair( frA_addr ) );
+
+ switch (opc2) {
+ case 0x42: // dscliq
+ DIP( "dscliq%s fr%u,fr%u,%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
+ assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
+ break;
+ case 0x62: // dscriq
+ DIP( "dscriq%s fr%u,fr%u,%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
+ assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
+ break;
+ }
+
+ putDReg_pair( frS_addr, mkexpr( frS ) );
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+/* DFP 64-bit format conversion instructions */
+static Bool dis_dfp_fmt_conv(UInt theInstr) {
+ UInt opc2 = ifieldOPClo10( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ IRExpr* round = get_IR_roundingmode_DFP();
+ UChar flag_rC = ifieldBIT0( theInstr );
+ IRTemp frB;
+ IRTemp frS;
+ Bool clear_CR1 = True;
+
+ switch (opc2) {
+ case 0x102: //dctdp
+ DIP( "dctdp%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+
+ frB = newTemp( Ity_D64 );
+ frS = newTemp( Ity_D64 );
+ assign( frB, getDReg( frB_addr ) );
+ assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
+ putDReg( frS_addr, mkexpr( frS ) );
+ break;
+ case 0x302: // drsp
+ DIP( "drsp%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ frB = newTemp( Ity_D64 );
+ frS = newTemp( Ity_D64 );
+ assign( frB, getDReg( frB_addr ) );
+ assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
+ putDReg( frS_addr, mkexpr( frS ) );
+ break;
+ case 0x122: // dctfix
+ DIP( "dctfix%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ frB = newTemp( Ity_D64 );
+ frS = newTemp( Ity_D64 );
+ assign( frB, getDReg( frB_addr ) );
+ assign( frS, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
+ putDReg( frS_addr, mkexpr( frS ) );
+ break;
+ case 0x322: // dcffix
+ DIP( "dcffix%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ frB = newTemp( Ity_D64 );
+ frS = newTemp( Ity_D64 );
+ assign( frB, getDReg( frB_addr ) );
+ assign( frS, binop( Iop_I64StoD64, round, mkexpr( frB ) ) );
+ putDReg( frS_addr, mkexpr( frS ) );
+ break;
+ }
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+/* Quad DFP format conversion instructions */
+static Bool dis_dfp_fmt_convq(UInt theInstr) {
+ UInt opc2 = ifieldOPClo10( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ IRExpr* round = get_IR_roundingmode_DFP();
+ IRTemp frB64 = newTemp( Ity_D64 );
+ IRTemp frB128 = newTemp( Ity_D128 );
+ IRTemp frS64 = newTemp( Ity_D64 );
+ IRTemp frS128 = newTemp( Ity_D128 );
+ UChar flag_rC = ifieldBIT0( theInstr );
+ Bool clear_CR1 = True;
+
+ switch (opc2) {
+ case 0x102: // dctqpq
+ DIP( "dctqpq%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ assign( frB64, getDReg( frB_addr ) );
+ assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
+ putDReg_pair( frS_addr, mkexpr( frS128 ) );
+ break;
+ case 0x122: // dctfixq
+ DIP( "dctfixq%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ assign( frB128, getDReg_pair( frB_addr ) );
+ assign( frS64, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
+ putDReg( frS_addr, mkexpr( frS64 ) );
+ break;
+ case 0x302: //drdpq
+ DIP( "drdpq%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ assign( frB128, getDReg_pair( frB_addr ) );
+ assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
+ putDReg( frS_addr, mkexpr( frS64 ) );
+ break;
+ case 0x322: // dcffixq
+ /* Have to introduce an IOP for this instruction so it will work
+ * on POWER 6 because emulating the instruction requires a POWER 7
+ * DFP instruction in the emulation code.
+ */
+ DIP( "dcffixq%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ assign( frB64, getDReg( frB_addr ) );
+ assign( frS128, unop( Iop_I64StoD128, mkexpr( frB64 ) ) );
+ putDReg_pair( frS_addr, mkexpr( frS128 ) );
+ break;
+ }
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
/*------------------------------------------------------------*/
/*--- AltiVec Instruction Translation ---*/
/*------------------------------------------------------------*/
@@ -13811,6 +14000,20 @@
if (!allow_DFP) goto decode_noDFP;
if (dis_dfp_arith( theInstr ))
goto decode_success;
+ case 0x102: // dctdp - DFP convert to DFP long
+ case 0x302: // drsp - DFP round to dfp short
+ case 0x122: // dctfix - DFP convert to fixed
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_fmt_conv( theInstr ))
+ goto decode_success;
+ goto decode_failure;
+ case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
+ if (!allow_VX)
+ goto decode_failure;
+ if (dis_dfp_fmt_conv( theInstr ))
+ goto decode_success;
+ goto decode_failure;
case 0x3CE: // fcfidus (implemented as native insn)
if (!allow_VX)
goto decode_noVX;
@@ -13823,6 +14026,17 @@
goto decode_failure;
}
+ opc2 = ifieldOPClo9( theInstr );
+ switch (opc2) {
+ case 0x42: // dscli, DFP shift left
+ case 0x62: // dscri, DFP shift right
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_shift( theInstr ))
+ goto decode_success;
+ goto decode_failure;
+ }
+
opc2 = IFIELD(theInstr, 1, 5);
switch (opc2) {
/* Floating Point Arith Instructions */
@@ -14037,6 +14251,16 @@
goto decode_success;
goto decode_failure;
+ case 0x102: // dctqpq - DFP convert to DFP extended
+ case 0x302: // drdpq - DFP round to dfp Long
+ case 0x122: // dctfixq - DFP convert to fixed quad
+ case 0x322: // dcffixq - DFP convert from fixed quad
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_fmt_convq( theInstr ))
+ goto decode_success;
+ goto decode_failure;
+
/* Floating Point Compare Instructions */
case 0x000: // fcmpu
case 0x020: // fcmpo
@@ -14096,10 +14320,24 @@
goto decode_failure;
default:
+ break; // Fall through...
+ }
+
+ opc2 = ifieldOPClo9( theInstr );
+ switch (opc2) {
+ case 0x42: // dscli, DFP shift left
+ case 0x62: // dscri, DFP shift right
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_shiftq( theInstr ))
+ goto decode_success;
goto decode_failure;
+ default:
+ goto decode_failure;
+ break;
}
break;
-
+
case 0x13:
switch (opc2) {
Modified: trunk/priv/host_ppc_isel.c (+140 -1)
===================================================================
--- trunk/priv/host_ppc_isel.c 2012-04-11 08:11:28 +01:00 (rev 2276)
+++ trunk/priv/host_ppc_isel.c 2012-04-12 18:19:48 +01:00 (rev 2277)
@@ -1,4 +1,5 @@
+
/*---------------------------------------------------------------*/
/*--- begin host_ppc_isel.c ---*/
/*---------------------------------------------------------------*/
@@ -3619,6 +3620,15 @@
}
if (e->tag == Iex_Unop) {
+ if (e->Iex.Binop.op == Iop_D32toD64) {
+ HReg fr_dst = newVRegF(env);
+ HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
+ addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
+ return fr_dst;
+ }
+ }
+
+ if (e->tag == Iex_Unop) {
switch (e->Iex.Unop.op) {
case Iop_D128HItoD64:
iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg );
@@ -3632,6 +3642,73 @@
}
}
+ if (e->tag == Iex_Binop) {
+ PPCFpOp fpop = Pfp_INVALID;
+
+ switch (e->Iex.Binop.op) {
+ /* shift instructions F64, I32 -> F64 */
+ case Iop_ShlD64: fpop = Pfp_DSCLI; break;
+ case Iop_ShrD64: fpop = Pfp_DSCRI; break;
+ default: break;
+ }
+ if (fpop != Pfp_INVALID) {
+ HReg fr_dst = newVRegF(env);
+ HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg1);
+ PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2);
+
+ addInstr(env, PPCInstr_DfpShift(fpop, fr_dst, fr_src, shift));
+ return fr_dst;
+ }
+ }
+
+ if (e->tag == Iex_Binop) {
+
+ switch (e->Iex.Binop.op) {
+ case Iop_D128toI64S: {
+ PPCFpOp fpop = Pfp_DCTFIXQ;
+ HReg fr_dst = newVRegF(env);
+ HReg r_srcHi = newVRegF(env);
+ HReg r_srcLo = newVRegF(env);
+
+ set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
+ return fr_dst;
+ }
+ case Iop_D128toD64: {
+ PPCFpOp fpop = Pfp_DRDPQ;
+ HReg fr_dst = newVRegF(env);
+ HReg r_srcHi = newVRegF(env);
+ HReg r_srcLo = newVRegF(env);
+
+ set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
+ return fr_dst;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (e->tag == Iex_Binop) {
+ PPCFpOp fpop = Pfp_INVALID;
+ switch (e->Iex.Binop.op) {
+ case Iop_D64toD32: fpop = Pfp_DRSP; break;
+ case Iop_I64StoD64: fpop = Pfp_DCFFIX; break;
+ case Iop_D64toI64S: fpop = Pfp_DCTFIX; break;
+ default: break;
+ }
+ if (fpop != Pfp_INVALID) {
+ HReg fr_dst = newVRegF(env);
+ HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
+ set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
+ addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
+ return fr_dst;
+ }
+ }
+
if (e->tag == Iex_Triop) {
PPCFpOp fpop = Pfp_INVALID;
@@ -3686,6 +3763,34 @@
return;
}
+ if (e->tag == Iex_Unop) {
+ PPCFpOp fpop = Pfp_INVALID;
+ HReg r_dstHi = newVRegF(env);
+ HReg r_dstLo = newVRegF(env);
+
+ if (e->Iex.Unop.op == Iop_I64StoD128) {
+ HReg r_src = iselDfp64Expr(env, e->Iex.Unop.arg);
+ fpop = Pfp_DCFFIXQ;
+
+ addInstr(env, PPCInstr_DfpI64StoD128(fpop, r_dstHi, r_dstLo,
+ r_src));
+ }
+ if (e->Iex.Unop.op == Iop_D64toD128) {
+ HReg r_src = iselDfp64Expr(env, e->Iex.Unop.arg);
+ fpop = Pfp_DCTQPQ;
+
+ /* Source is 64bit result is 128 bit. High 64bit source arg,
+ * is ignored by the instruction. Set high arg to r_src just
+ * to meet the vassert tests.
+ */
+ addInstr(env, PPCInstr_Dfp128Unary(fpop, r_dstHi, r_dstLo,
+ r_src, r_src));
+ }
+ *rHi = r_dstHi;
+ *rLo = r_dstLo;
+ return;
+ }
+
/* --------- OPS --------- */
if (e->tag == Iex_Binop) {
HReg r_srcHi;
@@ -3699,6 +3804,40 @@
*rLo = r_srcLo;
return;
break;
+ case Iop_D128toD64: {
+ PPCFpOp fpop = Pfp_DRDPQ;
+ HReg fr_dst = newVRegF(env);
+
+ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
+
+ /* Need to meet the interface spec but the result is
+ * just 64-bits so send the result back in both halfs.
+ */
+ *rHi = fr_dst;
+ *rLo = fr_dst;
+ return;
+ }
+ case Iop_ShlD128:
+ case Iop_ShrD128: {
+ HReg fr_dst_hi = newVRegF(env);
+ HReg fr_dst_lo = newVRegF(env);
+ PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2);
+ PPCFpOp fpop = Pfp_DSCLIQ; /* fix later if necessary */
+
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1);
+
+ if (e->Iex.Binop.op == Iop_ShrD128)
+ fpop = Pfp_DSCRIQ;
+
+ addInstr(env, PPCInstr_DfpShift128(fpop, fr_dst_hi, fr_dst_lo,
+ r_srcHi, r_srcLo, shift));
+
+ *rHi = fr_dst_hi;
+ *rLo = fr_dst_lo;
+ return;
+ }
default:
vex_printf( "ERROR: iselD128Expr_wrk, UNKNOWN binop case %d\n",
e->Iex.Binop.op );
@@ -3745,7 +3884,7 @@
}
ppIRExpr( e );
- vpanic( "iselD128Expr(ppc64)" );
+ vpanic( "iselDfp128Expr(ppc64)" );
}
Modified: trunk/priv/host_ppc_defs.h (+52 -7)
===================================================================
--- trunk/priv/host_ppc_defs.h 2012-04-11 08:11:28 +01:00 (rev 2276)
+++ trunk/priv/host_ppc_defs.h 2012-04-12 18:19:48 +01:00 (rev 2277)
@@ -368,12 +368,15 @@
Pfp_DQUAQ, Pfp_DRRNDQ,
/* Binary */
- Pfp_ADDD, Pfp_SUBD, Pfp_MULD, Pfp_DIVD,
- Pfp_ADDS, Pfp_SUBS, Pfp_MULS, Pfp_DIVS,
+ Pfp_ADDD, Pfp_SUBD, Pfp_MULD, Pfp_DIVD,
+ Pfp_ADDS, Pfp_SUBS, Pfp_MULS, Pfp_DIVS,
+ Pfp_DRSP, Pfp_DCTFIX, Pfp_DCTFIXQ, Pfp_DCFFIX,
/* Unary */
Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV, Pfp_RES, Pfp_RSQRTE,
- Pfp_FRIN, Pfp_FRIM, Pfp_FRIP, Pfp_FRIZ
+ Pfp_FRIN, Pfp_FRIM, Pfp_FRIP, Pfp_FRIZ,
+ Pfp_DSCLI, Pfp_DSCRI, Pfp_DSCLIQ, Pfp_DSCRIQ, Pfp_DCTDP, Pfp_DCTQPQ,
+ Pfp_DRDPQ, Pfp_DCFFIXQ
}
PPCFpOp;
@@ -492,9 +495,14 @@
Pin_AvLdVSCR, /* mtvscr */
Pin_AvCMov, /* AV conditional move */
Pin_Dfp64Unary, /* DFP64 unary op */
- Pin_Dfp128nary, /* DFP128 unary op */
+ Pin_Dfp128Unary, /* DFP128 unary op */
+ Pin_DfpShift, /* Decimal floating point shift by immediate value */
Pin_Dfp64Binary, /* DFP64 binary op */
- Pin_Dfp128Binary /* DFP128 binary op */
+ Pin_Dfp128Binary, /* DFP128 binary op */
+ Pin_DfpShift128, /* 128-bit Decimal floating point shift by
+ * immediate value */
+ Pin_DfpD128toD64, /* DFP 128 to DFP 64 op */
+ Pin_DfpI64StoD128, /* DFP signed integer to DFP 128 */
}
PPCInstrTag;
@@ -805,6 +813,12 @@
} Dfp64Binary;
struct {
PPCFpOp op;
+ HReg dst;
+ HReg src;
+ PPCRI* shift;
+ } DfpShift;
+ struct {
+ PPCFpOp op;
HReg dst_hi;
HReg dst_lo;
HReg src_hi;
@@ -820,6 +834,26 @@
HReg srcR_hi;
HReg srcR_lo;
} Dfp128Binary;
+ struct {
+ PPCFpOp op;
+ HReg dst_hi;
+ HReg dst_lo;
+ HReg src_hi;
+ HReg src_lo;
+ PPCRI* shift;
+ } DfpShift128;
+ struct {
+ PPCFpOp op;
+ HReg dst;
+ HReg src_hi;
+ HReg src_lo;
+ } DfpD128toD64;
+ struct {
+ PPCFpOp op;
+ HReg dst_hi;
+ HReg dst_lo;
+ HReg src;
+ } DfpI64StoD128;
} Pin;
}
PPCInstr;
@@ -881,8 +915,19 @@
extern PPCInstr* PPCInstr_Dfp64Unary ( PPCFpOp op, HReg dst, HReg src );
extern PPCInstr* PPCInstr_Dfp64Binary ( PPCFpOp op, HReg dst, HReg srcL,
HReg srcR );
-extern PPCInstr* PPCInstr_Dfp128Binary( PPCFpOp op, HReg dst_hi, HReg dst_lo,
- HReg srcR_hi, HReg srcR_lo );
+extern PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src,
+ PPCRI* shift );
+extern PPCInstr* PPCInstr_Dfp128Unary ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
+ HReg srcR_hi, HReg srcR_lo );
+extern PPCInstr* PPCInstr_Dfp128Binary ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
+ HReg srcR_hi, HReg srcR_lo );
+extern PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg src_hi,
+ HReg dst_lo, HReg src_lo,
+ PPCRI* shift );
+extern PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
+ HReg dst_lo, HReg src_lo);
+extern PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
+ HReg dst_lo, HReg src);
extern void ppPPCInstr(PPCInstr*, Bool mode64);
Modified: trunk/priv/host_ppc_defs.c (+322 -0)
===================================================================
--- trunk/priv/host_ppc_defs.c 2012-04-11 08:11:28 +01:00 (rev 2276)
+++ trunk/priv/host_ppc_defs.c 2012-04-12 18:19:48 +01:00 (rev 2277)
@@ -638,6 +638,13 @@
case Pfp_DFPMULQ: return "dmulq";
case Pfp_DFPDIV: return "ddivd";
case Pfp_DFPDIVQ: return "ddivq";
+ case Pfp_DCTDP: return "dctdp";
+ case Pfp_DRSP: return "drsp";
+ case Pfp_DCTFIX: return "dctfix";
+ case Pfp_DCFFIX: return "dcffix";
+ case Pfp_DCTQPQ: return "dctqpq";
+ case Pfp_DCFFIXQ: return "dcffixq";
+
default: vpanic("showPPCFpOp");
}
}
@@ -995,6 +1002,26 @@
i->Pin.Dfp64Binary.srcR = srcR;
return i;
}
+PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src, PPCRI* shift ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpShift;
+ i->Pin.DfpShift.op = op;
+ i->Pin.DfpShift.shift = shift;
+ i->Pin.DfpShift.src = src;
+ i->Pin.DfpShift.dst = dst;
+ return i;
+}
+PPCInstr* PPCInstr_Dfp128Unary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
+ HReg src_hi, HReg src_lo) {
+ PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
+ i->tag = Pin_Dfp128Unary;
+ i->Pin.Dfp128Unary.op = op;
+ i->Pin.Dfp128Unary.dst_hi = dst_hi;
+ i->Pin.Dfp128Unary.dst_lo = dst_lo;
+ i->Pin.Dfp128Unary.src_hi = src_hi;
+ i->Pin.Dfp128Unary.src_lo = src_lo;
+ return i;
+}
PPCInstr* PPCInstr_Dfp128Binary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
HReg srcR_hi, HReg srcR_lo) {
/* dst is used to pass the srcL argument and return the result */
@@ -1007,7 +1034,41 @@
i->Pin.Dfp128Binary.srcR_lo = srcR_lo;
return i;
}
+PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
+ HReg src_hi, HReg src_lo,
+ PPCRI* shift ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpShift128;
+ i->Pin.DfpShift128.op = op;
+ i->Pin.DfpShift128.shift = shift;
+ i->Pin.DfpShift128.src_hi = src_hi;
+ i->Pin.DfpShift128.src_lo = src_lo;
+ i->Pin.DfpShift128.dst_hi = dst_hi;
+ i->Pin.DfpShift128.dst_lo = dst_lo;
+ return i;
+}
+PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
+ HReg src_hi, HReg src_lo ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpD128toD64;
+ i->Pin.DfpD128toD64.op = op;
+ i->Pin.DfpD128toD64.src_hi = src_hi;
+ i->Pin.DfpD128toD64.src_lo = src_lo;
+ i->Pin.DfpD128toD64.dst = dst;
+ return i;
+}
+PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
+ HReg dst_lo, HReg src ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpI64StoD128;
+ i->Pin.DfpI64StoD128.op = op;
+ i->Pin.DfpI64StoD128.src = src;
+ i->Pin.DfpI64StoD128.dst_hi = dst_hi;
+ i->Pin.DfpI64StoD128.dst_lo = dst_lo;
+ return i;
+}
+
/*
Valid combo | fromI | int32 | syned | flt64 |
--------------------------------------------
@@ -1766,6 +1827,22 @@
ppHRegPPC(i->Pin.Dfp64Binary.srcR);
return;
+ case Pin_DfpShift:
+ vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift.op));
+ ppHRegPPC(i->Pin.DfpShift.dst);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpShift.src);
+ vex_printf(",");
+ ppPPCRI(i->Pin.DfpShift.shift);
+ return;
+
+ case Pin_Dfp128Unary:
+ vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Unary.op));
+ ppHRegPPC(i->Pin.Dfp128Unary.dst_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.Dfp128Unary.src_hi);
+ return;
+
case Pin_Dfp128Binary:
vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Binary.op));
ppHRegPPC(i->Pin.Dfp128Binary.dst_hi);
@@ -1773,6 +1850,31 @@
ppHRegPPC(i->Pin.Dfp128Binary.srcR_hi);
return;
+ case Pin_DfpShift128:
+ vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift128.op));
+ ppHRegPPC(i->Pin.DfpShift128.dst_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpShift128.src_hi);
+ vex_printf(",");
+ ppPPCRI(i->Pin.DfpShift128.shift);
+ return;
+
+ case Pin_DfpD128toD64:
+ vex_printf("%s ", showPPCFpOp(i->Pin.DfpD128toD64.op));
+ ppHRegPPC(i->Pin.DfpD128toD64.dst);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpD128toD64.src_hi);
+ vex_printf(",");
+ return;
+
+ case Pin_DfpI64StoD128:
+ vex_printf("%s ", showPPCFpOp(i->Pin.DfpI64StoD128.op));
+ ppHRegPPC(i->Pin.DfpI64StoD128.dst_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpI64StoD128.src);
+ vex_printf(",");
+ return;
+
default:
vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
vpanic("ppPPCInstr");
@@ -2049,12 +2151,40 @@
addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcL);
addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcR);
return;
+ case Pin_DfpShift:
+ addRegUsage_PPCRI(u, i->Pin.DfpShift.shift);
+ addHRegUse(u, HRmWrite, i->Pin.DfpShift.src);
+ addHRegUse(u, HRmWrite, i->Pin.DfpShift.dst);
+ return;
+ case Pin_Dfp128Unary:
+ addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_hi);
+ addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_lo);
+ addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_hi);
+ addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_lo);
+ return;
case Pin_Dfp128Binary:
addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_hi);
addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_lo);
addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_hi);
addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_lo);
return;
+ case Pin_DfpShift128:
+ addRegUsage_PPCRI(u, i->Pin.DfpShift128.shift);
+ addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_hi);
+ addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_lo);
+ addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_hi);
+ addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_lo);
+ return;
+ case Pin_DfpD128toD64:
+ addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_hi);
+ addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_lo);
+ addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.dst);
+ return;
+ case Pin_DfpI64StoD128:
+ addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.src);
+ addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_hi);
+ addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_lo);
+ return;
default:
ppPPCInstr(i, mode64);
@@ -2260,12 +2390,40 @@
mapReg(m, &i->Pin.Dfp64Binary.srcL);
mapReg(m, &i->Pin.Dfp64Binary.srcR);
return;
+ case Pin_DfpShift:
+ mapRegs_PPCRI(m, i->Pin.DfpShift.shift);
+ mapReg(m, &i->Pin.DfpShift.src);
+ mapReg(m, &i->Pin.DfpShift.dst);
+ return;
+ case Pin_Dfp128Unary:
+ mapReg(m, &i->Pin.Dfp128Unary.dst_hi);
+ mapReg(m, &i->Pin.Dfp128Unary.dst_lo);
+ mapReg(m, &i->Pin.Dfp128Unary.src_hi);
+ mapReg(m, &i->Pin.Dfp128Unary.src_lo);
+ return;
case Pin_Dfp128Binary:
mapReg(m, &i->Pin.Dfp128Binary.dst_hi);
mapReg(m, &i->Pin.Dfp128Binary.dst_lo);
mapReg(m, &i->Pin.Dfp128Binary.srcR_hi);
mapReg(m, &i->Pin.Dfp128Binary.srcR_lo);
return;
+ case Pin_DfpShift128:
+ mapRegs_PPCRI(m, i->Pin.DfpShift128.shift);
+ mapReg(m, &i->Pin.DfpShift128.src_hi);
+ mapReg(m, &i->Pin.DfpShift128.src_lo);
+ mapReg(m, &i->Pin.DfpShift128.dst_hi);
+ mapReg(m, &i->Pin.DfpShift128.dst_lo);
+ return;
+ case Pin_DfpD128toD64:
+ mapReg(m, &i->Pin.DfpD128toD64.src_hi);
+ mapReg(m, &i->Pin.DfpD128toD64.src_lo);
+ mapReg(m, &i->Pin.DfpD128toD64.dst);
+ return;
+ case Pin_DfpI64StoD128:
+ mapReg(m, &i->Pin.DfpI64StoD128.src);
+ mapReg(m, &i->Pin.DfpI64StoD128.dst_hi);
+ mapReg(m, &i->Pin.DfpI64StoD128.dst_lo);
+ return;
default:
ppPPCInstr(i, mode64);
@@ -2601,6 +2759,21 @@
return emit32(p, theInstr);
}
+static UChar* mkFormZ22 ( UChar* p, UInt opc1, UInt r1, UInt r2,
+ UInt constant, UInt opc2, UInt b0 )
+{
+ UInt theInstr;
+ vassert(opc1 < 0x40);
+ vassert(r1 < 0x20);
+ vassert(r2 < 0x20);
+ vassert(constant < 0x40); /* 6 bit constant */
+ vassert(opc2 < 0x200); /* 9 bit field */
+ vassert(b0 < 0x2);
+ theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
+ (constant<<10) | (opc2<<1) | (b0));
+ return emit32(p, theInstr);
+}
+
static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
PPCAMode* am, Bool mode64 )
{
@@ -4050,6 +4223,19 @@
case Pfp_MOV: // fmr, PPC32 p410
p = mkFormX( p, 63, fr_dst, 0, fr_src, 72, 0 );
break;
+ case Pfp_DCTDP: // D32 to D64
+ p = mkFormX( p, 59, fr_dst, 0, fr_src, 258, 0 );
+ break;
+ case Pfp_DRSP: // D64 to D32
+ p = mkFormX( p, 59, fr_dst, 0, fr_src, 770, 0 );
+ break;
+ case Pfp_DCFFIX: // I64 to D64 conversion
+ /* ONLY WORKS ON POWER7 */
+ p = mkFormX( p, 59, fr_dst, 0, fr_src, 802, 0);
+ break;
+ case Pfp_DCTFIX: // D64 to I64 conversion
+ p = mkFormX( p, 59, fr_dst, 0, fr_src, 290, 0);
+ break;
default:
goto bad;
}
@@ -4083,6 +4269,56 @@
goto done;
}
+ case Pin_DfpShift: {
+ UInt fr_src = fregNo(i->Pin.DfpShift.src);
+ UInt fr_dst = fregNo(i->Pin.DfpShift.dst);
+ UInt shift;
+
+ shift = i->Pin.DfpShift.shift->Pri.Imm;
+
+ switch (i->Pin.DfpShift.op) {
+ case Pfp_DSCLI: /* dscli, DFP shift left by fr_srcR */
+ p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 66, 0 );
+ break;
+ case Pfp_DSCRI: /* dscri, DFP shift right by fr_srcR */
+ p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 98, 0 );
+ break;
+ default:
+ vex_printf("ERROR: emit_PPCInstr default case\n");
+ goto bad;
+ }
+ goto done;
+ }
+
+ case Pin_Dfp128Unary: {
+ UInt fr_dstHi = fregNo(i->Pin.Dfp128Unary.dst_hi);
+ UInt fr_dstLo = fregNo(i->Pin.Dfp128Unary.dst_lo);
+ UInt fr_srcLo = fregNo(i->Pin.Dfp128Unary.src_lo);
+
+ /* Do instruction with 128-bit source operands in registers (10,11)
+ * and (12,13).
+ */
+ switch (i->Pin.Dfp128Unary.op) {
+ case Pfp_DCTQPQ: // D64 to D128, srcLo holds 64 bit operand
+ p = mkFormX( p, 63, 12, 0, fr_srcLo, 72, 0);
+
+ p = mkFormX( p, 63, 10, 0, 12, 258, 0 );
+
+ /* The instruction will put the 128-bit result in
+ * registers (10,11). Note, the operand in the instruction only
+ * reference the first of the two registers in the pair.
+ */
+ p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
+ p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
+ break;
+ default:
+ vex_printf("Error: emit_PPCInstr case Pin_Dfp128Unary, case inst Default\
+\n");
+ goto bad;
+ }
+ goto done;
+ }
+
case Pin_Dfp128Binary: {
/* dst is used to supply the left source operand and return
* the result.
@@ -4129,6 +4365,92 @@
goto done;
}
+ case Pin_DfpShift128: {
+ UInt fr_src_hi = fregNo(i->Pin.DfpShift128.src_hi);
+ UInt fr_src_lo = fregNo(i->Pin.DfpShift128.src_lo);
+ UInt fr_dst_hi = fregNo(i->Pin.DfpShift128.dst_hi);
+ UInt fr_dst_lo = fregNo(i->Pin.DfpShift128.dst_lo);
+ UInt shift;
+
+ shift = i->Pin.DfpShift128.shift->Pri.Imm;
+
+ /* setup source operand in register 12, 13 pair */
+ p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0);
+ p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0);
+
+ /* execute instruction putting result in register 10, 11 pair */
+ switch (i->Pin.DfpShift128.op) {
+ case Pfp_DSCLIQ: /* dscliq, DFP shift left, fr_srcR is the integer
+ * shift amount.
+ */
+ p = mkFormZ22( p, 63, 10, 12, shift, 66, 0 );
+ break;
+ case Pfp_DSCRIQ: /* dscriq, DFP shift right, fr_srcR is the integer
+ * shift amount.
+ */
+ p = mkFormZ22( p, 63, 10, 12, shift, 98, 0 );
+ break;
+ default:
+ vex_printf("ERROR: emit_PPCInstr quad default case %d \n",
+ i->Pin.DfpShift128.op);
+ goto bad;
+ }
+
+ /* The instruction put the 128-bit result in registers (10,11).
+ * Note, the operand in the instruction only reference the first of
+ * the two registers in the pair.
+ */
+ p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0);
+ p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0);
+ goto done;
+ }
+
+ case Pin_DfpD128toD64: {
+ UInt fr_dst = fregNo( i->Pin.DfpD128toD64.dst );
+ UInt fr_srcHi = fregNo( i->Pin.DfpD128toD64.src_hi );
+ UInt fr_srcLo = fregNo( i->Pin.DfpD128toD64.src_lo );
+
+ /* Setup the upper and lower registers of the source operand
+ * register pair.
+ */
+ p = mkFormX( p, 63, 10, 0, fr_dst, 72, 0 );
+ p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0 );
+ p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0 );
+
+ /* Do instruction with 128-bit source operands in registers (10,11) */
+ switch (i->Pin.Dfp128Binary.op) {
+ case Pfp_DRDPQ:
+ p = mkFormX( p, 63, 10, 0, 12, 770, 0 );
+ break;
+ case Pfp_DCTFIXQ:
+ p = mkFormX( p, 63, 10, 0, 12, 290, 0 );
+ break;
+ default:
+ goto bad;
+ }
+
+ /* The instruction will put the 64-bit result in registers 10. */
+ p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0);
+ goto done;
+ }
+ case Pin_DfpI64StoD128: {
+ UInt fr_dstHi = fregNo( i->Pin.DfpI64StoD128.dst_hi );
+ UInt fr_dstLo = fregNo( i->Pin.DfpI64StoD128.dst_lo );
+ UInt fr_src = fregNo( i->Pin.DfpI64StoD128.src );
+
+ switch (i->Pin.Dfp128Binary.op) {
+ case Pfp_DCFFIXQ:
+ p = mkFormX( p, 63, 10, 11, fr_src, 802, 0 );
+ break;
+ default:
+ goto bad;
+ }
+
+ /* The instruction will put the 64-bit result in registers 10, 11. */
+ p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
+ p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
+ goto done;
+ }
default:
goto bad;
}
Modified: trunk/priv/ir_defs.c (+43 -1)
===================================================================
--- trunk/priv/ir_defs.c 2012-04-11 08:11:28 +01:00 (rev 2276)
+++ trunk/priv/ir_defs.c 2012-04-12 18:19:48 +01:00 (rev 2277)
@@ -937,14 +937,26 @@
case Iop_Fixed32UToF32x2_RN: vex_printf("Fixed32UToF32x2_RN"); return;
case Iop_Fixed32SToF32x2_RN: vex_printf("Fixed32SToF32x2_RN"); return;
+ case Iop_D32toD64: vex_printf("D32toD64"); return;
+ case Iop_D64toD32: vex_printf("D64toD32"); return;
case Iop_AddD64: vex_printf("AddD64"); return;
case Iop_SubD64: vex_printf("SubD64"); return;
case Iop_MulD64: vex_printf("MulD64"); return;
case Iop_DivD64: vex_printf("DivD64"); return;
+ case Iop_ShlD64: vex_printf("ShlD64"); return;
+ case Iop_ShrD64: vex_printf("ShrD64"); return;
+ case Iop_D64toI64S: vex_printf("D64toI64S"); return;
+ case Iop_I64StoD64: vex_printf("I64StoD64"); return;
+ case Iop_I64StoD128: vex_printf("I64StoD128"); return;
+ case Iop_D64toD128: vex_printf("D64toD128"); return;
+ case Iop_D128toD64: vex_printf("D128toD64"); return;
+ case Iop_D128toI64S: vex_printf("D128toI64S"); return;
case Iop_AddD128: vex_printf("AddD128"); return;
case Iop_SubD128: vex_printf("SubD128"); return;
case Iop_MulD128: vex_printf("MulD128"); return;
case Iop_DivD128: vex_printf("DivD128"); return;
+ case Iop_ShlD128: vex_printf("ShlD128"); return;
+ case Iop_ShrD128: vex_printf("ShrD128"); return;
case Iop_D64HLtoD128: vex_printf("D64HLtoD128"); return;
case Iop_D128HItoD64: vex_printf("D128HItoD64"); return;
case Iop_D128LOtoD64: vex_printf("D128LOtoD64"); return;
@@ -2606,19 +2618,49 @@
case Iop_F128toF32: BINARY(ity_RMode,Ity_F128, Ity_F32);
case Iop_F128toF64: BINARY(ity_RMode,Ity_F128, Ity_F64);
+ case Iop_D32toD64:
+ UNARY(Ity_D64, Ity_D64);
+
+ case Iop_D64toD128:
+ UNARY(Ity_D64, Ity_D128);
+
+ case Iop_I64StoD128: /* I64 bit pattern stored in Float register */
+ UNARY(Ity_D64, Ity_D128);
+
case Iop_D128HItoD64:
case Iop_D128LOtoD64:
UNARY(Ity_D128, Ity_D64);
+ case Iop_D128toI64S:
+ BINARY(ity_RMode, Ity_D128, Ity_D64);
+
case Iop_D64HLtoD128:
- BINARY(Ity_D64,Ity_D64, Ity_D128);
+ BINARY(Ity_D64, Ity_D64, Ity_D128);
+ case Iop_ShlD64:
+ case Iop_ShrD64:
+ BINARY(Ity_D64, Ity_I8, Ity_D64 );
+
+ case Iop_D64toD32:
+ case Iop_D64toI64S:
+ BINARY(ity_RMode, Ity_D64, Ity_D64);
+
+ case Iop_I64StoD64: /* I64 bit pattern stored in Float register */
+ BINARY(ity_RMode, Ity_D64, Ity_D64);
+
+ case Iop_ShlD128:
+ case Iop_ShrD128:
+ BINARY(Ity_D128, Ity_I8, Ity_D128 );
+
case Iop_AddD64:
case Iop_SubD64:
case Iop_MulD64:
case Iop_DivD64:
TERNARY( ity_RMode, Ity_D64, Ity_D64, Ity_D64 );
+ case Iop_D128toD64:
+ BINARY( ity_RMode, Ity_D128, Ity_D64 );
+
case Iop_AddD128:
case Iop_SubD128:
case Iop_MulD128:
|