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 ---*/
/*------------------------------------------------------------*/
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;
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 */
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
if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
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) {
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");
}
}
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 */
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 |
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);
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");
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);
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);
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 )
{
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;
}
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.
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;
}
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;
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;
HReg srcL;
HReg srcR;
} Dfp64Binary;
+ struct {
+ PPCFpOp op;
+ HReg dst;
+ HReg src;
+ PPCRI* shift;
+ } DfpShift;
struct {
PPCFpOp op;
HReg dst_hi;
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;
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);
+
/*---------------------------------------------------------------*/
/*--- begin host_ppc_isel.c ---*/
/*---------------------------------------------------------------*/
return r_dst;
}
+ 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:
}
}
+ 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;
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;
*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 );
}
ppIRExpr( e );
- vpanic( "iselD128Expr(ppc64)" );
+ vpanic( "iselDfp128Expr(ppc64)" );
}
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;
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_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:
*/
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,