(Carl Love, carll@us.ibm.com). Bug 298080.
git-svn-id: svn://svn.valgrind.org/vex/trunk@2312
return IFIELD( instr, 1, 9 );
}
+/* Extract 8-bit secondary opcode, instr[8:1] */
+static UInt ifieldOPClo8 ( UInt instr) {
+ return IFIELD( instr, 1, 8 );
+}
+
/* Extract 5-bit secondary opcode, instr[5:1] */
static UInt ifieldOPClo5 ( UInt instr) {
return IFIELD( instr, 1, 5 );
return True;
}
+static Bool dis_dfp_round( UInt theInstr ) {
+ UChar frS_addr = ifieldRegDS(theInstr);
+ UChar R = IFIELD(theInstr, 16, 1);
+ UChar RMC = IFIELD(theInstr, 9, 2);
+ UChar frB_addr = ifieldRegB( theInstr );
+ UChar flag_rC = ifieldBIT0( theInstr );
+ IRTemp frB = newTemp( Ity_D64 );
+ IRTemp frS = newTemp( Ity_D64 );
+ UInt opc2 = ifieldOPClo8( theInstr );
+ Bool clear_CR1 = True;
+
+ switch (opc2) {
+ /* drintn, is the same as drintx. The only difference is this
+ * instruction does not generate an exception for an inexact operation.
+ * Currently not supporting inexact exceptions.
+ */
+ case 0x63: // drintx
+ case 0xE3: // drintn
+ DIP( "drintx/drintn%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+
+ /* pass the value of R and RMC in the same field */
+ assign( frB, getDReg( frB_addr ) );
+ assign( frS, binop( Iop_RoundD64toInt,
+ mkU32( ( R << 3 ) | RMC ),
+ mkexpr( frB ) ) );
+ putDReg( frS_addr, mkexpr( frS ) );
+ break;
+ default:
+ vex_printf("dis_dfp_round(ppc)(opc2)\n");
+ return False;
+ }
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+static Bool dis_dfp_roundq(UInt theInstr) {
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ UChar R = IFIELD(theInstr, 16, 1);
+ UChar RMC = IFIELD(theInstr, 9, 2);
+ UChar flag_rC = ifieldBIT0( theInstr );
+ IRTemp frB = newTemp( Ity_D128 );
+ IRTemp frS = newTemp( Ity_D128 );
+ Bool clear_CR1 = True;
+ UInt opc2 = ifieldOPClo8( theInstr );
+
+ switch (opc2) {
+ /* drintnq, is the same as drintxq. The only difference is this
+ * instruction does not generate an exception for an inexact operation.
+ * Currently not supporting inexact exceptions.
+ */
+ case 0x63: // drintxq
+ case 0xE3: // drintnq
+ DIP( "drintxq/drintnq%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+
+ /* pass the value of R and RMC in the same field */
+ assign( frB, getDReg_pair( frB_addr ) );
+ assign( frS, binop( Iop_RoundD128toInt,
+ mkU32( ( R << 3 ) | RMC ),
+ mkexpr( frB ) ) );
+ putDReg_pair( frS_addr, mkexpr( frS ) );
+ break;
+ default:
+ vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
+ return False;
+ }
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
+ UInt opc2 = ifieldOPClo8( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frA_addr = ifieldRegA( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ UChar flag_rC = ifieldBIT0( theInstr );
+ UInt TE_value = IFIELD(theInstr, 16, 4);
+ UInt TE_sign = IFIELD(theInstr, 20, 1);
+ UInt RMC = IFIELD(theInstr, 9, 2);
+ IRTemp frA = newTemp( Ity_D64 );
+ IRTemp frB = newTemp( Ity_D64 );
+ IRTemp frS = newTemp( Ity_D64 );
+ Bool clear_CR1 = True;
+
+ assign( frB, getDReg( frB_addr ) );
+
+ switch (opc2) {
+ case 0x43: // dquai
+ DIP( "dquai%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ IRTemp TE_D64 = newTemp( Ity_D64 );
+
+ /* Generate a reference DFP value frA with the desired exponent
+ * given by TE using significand from frB. Need to add the bias
+ * 398 to TE. TE is stored as a 2's complement number.
+ */
+ if (TE_sign == 1) {
+ /* Take 2's complement of the 5-bit value and subtract from bias.
+ * Bias is adjusted for the +1 required when taking 2's complement.
+ */
+ assign( TE_D64,
+ unop( Iop_ReinterpI64asD64,
+ binop( Iop_Sub64, mkU64( 397 ),
+ binop( Iop_And64, mkU64( 0xF ),
+ unop( Iop_Not64, mkU64( TE_value ) )
+ ) ) ) );
+
+ } else {
+ assign( TE_D64,
+ unop( Iop_ReinterpI64asD64,
+ binop( Iop_Add64, mkU64( 398 ), mkU64( TE_value ) ) ) );
+ }
+
+ assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_D64 ),
+ unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
+
+ assign( frS, triop( Iop_QuantizeD64,
+ mkU32( RMC ),
+ mkexpr( frA ),
+ mkexpr( frB ) ) );
+ break;
+
+ case 0x3: // dqua
+ DIP( "dqua%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ assign( frA, getDReg( frA_addr ) );
+ assign( frS, triop( Iop_QuantizeD64,
+ mkU32( RMC ),
+ mkexpr( frA ),
+ mkexpr( frB ) ) );
+ break;
+ case 0x23: // drrnd
+ DIP( "drrnd%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ assign( frA, getDReg( frA_addr ) );
+ assign( frS, triop( Iop_SignificanceRoundD64,
+ mkU32( RMC ),
+ mkexpr( frA ),
+ mkexpr( frB ) ) );
+ break;
+ default:
+ vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
+ return False;
+ }
+ putDReg( frS_addr, mkexpr( frS ) );
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
+ UInt opc2 = ifieldOPClo8( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frA_addr = ifieldRegA( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ UChar flag_rC = ifieldBIT0( theInstr );
+ UInt TE_value = IFIELD(theInstr, 16, 4);
+ UInt TE_sign = IFIELD(theInstr, 20, 1);
+ UInt RMC = IFIELD(theInstr, 9, 2);
+ IRTemp frA = newTemp( Ity_D128 );
+ IRTemp frB = newTemp( Ity_D128 );
+ IRTemp frS = newTemp( Ity_D128 );
+ Bool clear_CR1 = True;
+
+ assign( frB, getDReg_pair( frB_addr ) );
+
+ switch (opc2) {
+ case 0x43: // dquaiq
+ DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ IRTemp TE_D64 = newTemp( Ity_D64 );
+
+ /* Generate a reference DFP value frA with the desired exponent
+ * given by TE using significand of 1. Need to add the bias
+ * 6176 to TE.
+ */
+ if (TE_sign == 1) {
+ /* Take 2's complement of the 5-bit value and subtract from bias.
+ * Bias adjusted for the +1 required when taking 2's complement.
+ */
+ assign( TE_D64,
+ unop( Iop_ReinterpI64asD64,
+ binop( Iop_Sub64, mkU64( 6175 ),
+ binop( Iop_And64, mkU64( 0xF ),
+ unop( Iop_Not64, mkU64( TE_value ) )
+ ) ) ) );
+
+ } else {
+ assign( TE_D64,
+ unop( Iop_ReinterpI64asD64,
+ binop( Iop_Add64, mkU64( 6176 ), mkU64( TE_value ) )
+ ) );
+ }
+
+ assign( frA,
+ binop( Iop_InsertExpD128, mkexpr( TE_D64 ),
+ unop( Iop_D64toD128,
+ unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
+ assign( frS, triop( Iop_QuantizeD128,
+ mkU32( RMC ),
+ mkexpr( frA ),
+ mkexpr( frB ) ) );
+ break;
+ case 0x3: // dquaq
+ DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ assign( frA, getDReg_pair( frA_addr ) );
+ assign( frS, triop( Iop_QuantizeD128,
+ mkU32( RMC ),
+ mkexpr( frA ),
+ mkexpr( frB ) ) );
+ break;
+ case 0x23: // drrndq
+ DIP( "drrndq%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ assign( frA, getDReg_pair( frA_addr ) );
+ assign( frS, triop( Iop_SignificanceRoundD128,
+ mkU32( RMC ),
+ mkexpr( frA ),
+ mkexpr( frB ) ) );
+ break;
+ default:
+ vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
+ return False;
+ }
+ putDReg_pair( frS_addr, mkexpr( frS ) );
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+static Bool dis_dfp_extract_insert(UInt theInstr) {
+ UInt opc2 = ifieldOPClo10( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frA_addr = ifieldRegA( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ UChar flag_rC = ifieldBIT0( theInstr );
+ Bool clear_CR1 = True;
+
+ IRTemp frA = newTemp( Ity_D64 );
+ IRTemp frB = newTemp( Ity_D64 );
+ IRTemp frS = newTemp( Ity_D64 );
+
+ assign( frA, getDReg( frA_addr ) );
+ assign( frB, getDReg( frB_addr ) );
+
+ switch (opc2) {
+ case 0x162: // dxex
+ DIP( "dxex%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ assign( frS, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
+ break;
+ case 0x362: // diex
+ DIP( "diex%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ assign( frS, binop( Iop_InsertExpD64, mkexpr( frA ), mkexpr( frB ) ) );
+ break;
+ default:
+ vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
+ return False;
+ }
+
+ putDReg( frS_addr, mkexpr( frS ) );
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+static Bool dis_dfp_extract_insertq(UInt theInstr) {
+ UInt opc2 = ifieldOPClo10( theInstr );
+ UChar frS_addr = ifieldRegDS( theInstr );
+ UChar frA_addr = ifieldRegA( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ UChar flag_rC = ifieldBIT0( theInstr );
+
+ IRTemp frA = newTemp( Ity_D64 );
+ IRTemp frB = newTemp( Ity_D128 );
+ IRTemp frS64 = newTemp( Ity_D64 );
+ IRTemp frS = newTemp( Ity_D128 );
+ Bool clear_CR1 = True;
+
+ assign( frB, getDReg_pair( frB_addr ) );
+
+ switch (opc2) {
+ case 0x162: // dxexq
+ DIP( "dxexq%s fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frB_addr );
+ /* Instruction actually returns a 64-bit result. So as to be
+ * consistent and not have to add a new struct, the emulation returns
+ * the 64-bit result in the upper and lower register.
+ */
+ assign( frS64, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
+ putDReg( frS_addr, mkexpr( frS64 ) );
+ break;
+ case 0x362: // diexq
+ DIP( "diexq%s fr%u,fr%u,fr%u\n",
+ flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
+ assign( frA, getDReg( frA_addr ) );
+ assign( frS, binop( Iop_InsertExpD128, mkexpr( frA ), mkexpr( frB ) ) );
+ putDReg_pair( frS_addr, mkexpr( frS ) );
+ break;
+ default:
+ vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
+ return False;
+ }
+
+ if (flag_rC && clear_CR1) {
+ putCR321( 1, mkU8( 0 ) );
+ putCR0( 1, mkU8( 0 ) );
+ }
+
+ return True;
+}
+
+/* DFP 64-bit comparison instructions */
+static Bool dis_dfp_compare(UInt theInstr) {
+ /* X-Form */
+ UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
+ UChar frA_addr = ifieldRegA( theInstr );
+ UChar frB_addr = ifieldRegB( theInstr );
+ UInt opc1 = ifieldOPC( theInstr );
+ IRTemp frA;
+ IRTemp frB;
+
+ IRTemp ccIR = newTemp( Ity_I32 );
+ IRTemp ccPPC32 = newTemp( Ity_I32 );
+
+
+ /* Note: Differences between dcmpu and dcmpo are only in exception
+ flag settings, which aren't supported anyway. */
+ switch (opc1) {
+ case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
+ DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
+ frA = newTemp( Ity_D64 );
+ frB = newTemp( Ity_D64 );
+
+ assign( frA, getDReg( frA_addr ) );
+ assign( frB, getDReg( frB_addr ) );
+
+ assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
+ break;
+ case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
+ DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
+ frA = newTemp( Ity_D128 );
+ frB = newTemp( Ity_D128 );
+
+ assign( frA, getDReg_pair( frA_addr ) );
+ assign( frB, getDReg_pair( frB_addr ) );
+ assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
+ break;
+ default:
+ vex_printf("dis_dfp_compare(ppc)(opc2)\n");
+ return False;
+ }
+
+ /* Map compare result from IR to PPC32 */
+ /*
+ FP cmp result | PPC | IR
+ --------------------------
+ UN | 0x1 | 0x45
+ EQ | 0x2 | 0x40
+ GT | 0x4 | 0x00
+ LT | 0x8 | 0x01
+ */
+
+ assign( ccPPC32,
+ binop( Iop_Shl32,
+ mkU32( 1 ),
+ unop( Iop_32to8,
+ binop( Iop_Or32,
+ binop( Iop_And32,
+ unop( Iop_Not32,
+ binop( Iop_Shr32,
+ mkexpr( ccIR ),
+ mkU8( 5 ) ) ),
+ mkU32( 2 ) ),
+ binop( Iop_And32,
+ binop( Iop_Xor32,
+ mkexpr( ccIR ),
+ binop( Iop_Shr32,
+ mkexpr( ccIR ),
+ mkU8( 6 ) ) ),
+ mkU32( 1 ) ) ) ) ) );
+
+ putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
+ return True;
+}
+
/*------------------------------------------------------------*/
/*--- AltiVec Instruction Translation ---*/
/*------------------------------------------------------------*/
if (!allow_DFP) goto decode_noDFP;
if (dis_dfp_arith( theInstr ))
goto decode_success;
+ case 0x82: // dcmpo, DFP comparison ordered instruction
+ case 0x282: // dcmpu, DFP comparison unordered instruction
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_compare( theInstr ) )
+ goto decode_success;
+ goto decode_failure;
case 0x102: // dctdp - DFP convert to DFP long
case 0x302: // drsp - DFP round to dfp short
case 0x122: // dctfix - DFP convert to fixed
if (dis_dfp_fmt_conv( theInstr ))
goto decode_success;
goto decode_failure;
+ case 0x162: // dxex - Extract exponent
+ case 0x362: // diex - Insert exponent
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_extract_insert( theInstr ) )
+ goto decode_success;
+ goto decode_failure;
case 0x3CE: // fcfidus (implemented as native insn)
if (!allow_VX)
goto decode_noVX;
goto decode_failure;
}
+ opc2 = ifieldOPClo8( theInstr );
+ switch (opc2) {
+ case 0x3: // dqua - DFP Quantize
+ case 0x23: // drrnd - DFP Reround
+ case 0x43: // dquai - DFP Quantize immediate
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_quantize_sig_rrnd( theInstr ) )
+ goto decode_success;
+ goto decode_failure;
+ case 0x63: // drintx - Round to an integer value
+ case 0xE3: // drintn - Round to an integer value
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_round( theInstr ) ) {
+ goto decode_success;
+ }
+ goto decode_failure;
+ default:
+ break; /* fall through to next opc2 check */
+ }
+
opc2 = IFIELD(theInstr, 1, 5);
switch (opc2) {
/* Floating Point Arith Instructions */
if (dis_dfp_arithq( theInstr ))
goto decode_success;
goto decode_failure;
+ case 0x162: // dxexq - DFP Extract exponent
+ case 0x362: // diexq - DFP Insert exponent
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_extract_insertq( theInstr ))
+ goto decode_success;
+ goto decode_failure;
+
+ case 0x82: // dcmpoq, DFP comparison ordered instruction
+ case 0x282: // dcmpuq, DFP comparison unordered instruction
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_compare( theInstr ) )
+ goto decode_success;
+ goto decode_failure;
case 0x102: // dctqpq - DFP convert to DFP extended
case 0x302: // drdpq - DFP round to dfp Long
goto decode_success;
goto decode_failure;
default:
- goto decode_failure;
break;
}
+
+ opc2 = ifieldOPClo8( theInstr );
+ switch (opc2) {
+ case 0x3: // dquaq - DFP Quantize Quad
+ case 0x23: // drrndq - DFP Reround Quad
+ case 0x43: // dquaiq - DFP Quantize immediate Quad
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_quantize_sig_rrndq( theInstr ))
+ goto decode_success;
+ goto decode_failure;
+ case 0x63: // drintxq - DFP Round to an integer value
+ case 0xE3: // drintnq - DFP Round to an integer value
+ if (!allow_DFP)
+ goto decode_failure;
+ if (dis_dfp_roundq( theInstr ))
+ goto decode_success;
+ goto decode_failure;
+
+ default:
+ goto decode_failure;
+ }
break;
case 0x13:
This is precisely the behaviour that the register allocator needs
to impose its decisions on the instructions it processes. */
-#define N_HREG_REMAP 5
+#define N_HREG_REMAP 6
typedef
struct {
case Pfp_DCFFIX: return "dcffix";
case Pfp_DCTQPQ: return "dctqpq";
case Pfp_DCFFIXQ: return "dcffixq";
-
+ case Pfp_DQUA: return "dqua";
+ case Pfp_DQUAQ: return "dquaq";
+ case Pfp_DXEX: return "dxex";
+ case Pfp_DXEXQ: return "dxexq";
+ case Pfp_DIEX: return "diex";
+ case Pfp_DIEXQ: return "diexq";
+ case Pfp_RRDTR: return "rrdtr";
default: vpanic("showPPCFpOp");
}
}
i->Pin.DfpShift128.dst_lo = dst_lo;
return i;
}
+PPCInstr* PPCInstr_DfpRound ( HReg dst, HReg src, PPCRI* r_rmc ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpRound;
+ i->Pin.DfpRound.dst = dst;
+ i->Pin.DfpRound.src = src;
+ i->Pin.DfpRound.r_rmc = r_rmc;
+ return i;
+}
+PPCInstr* PPCInstr_DfpRound128 ( HReg dst_hi, HReg dst_lo, HReg src_hi,
+ HReg src_lo, PPCRI* r_rmc ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpRound128;
+ i->Pin.DfpRound128.dst_hi = dst_hi;
+ i->Pin.DfpRound128.dst_lo = dst_lo;
+ i->Pin.DfpRound128.src_hi = src_hi;
+ i->Pin.DfpRound128.src_lo = src_lo;
+ i->Pin.DfpRound128.r_rmc = r_rmc;
+ return i;
+}
+PPCInstr* PPCInstr_DfpQuantize ( PPCAvFpOp op, HReg dst, HReg srcL, HReg srcR,
+ PPCRI* rmc ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpQuantize;
+ i->Pin.DfpQuantize.op = op;
+ i->Pin.DfpQuantize.dst = dst;
+ i->Pin.DfpQuantize.srcL = srcL;
+ i->Pin.DfpQuantize.srcR = srcR;
+ i->Pin.DfpQuantize.rmc = rmc;
+ return i;
+}
+PPCInstr* PPCInstr_DfpQuantize128 ( PPCAvFpOp op, HReg dst_hi, HReg dst_lo,
+ HReg src_hi, HReg src_lo, PPCRI* rmc ) {
+ /* dst is used to pass left operand in and return result */
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_DfpQuantize128;
+ i->Pin.DfpQuantize128.op = op;
+ i->Pin.DfpQuantize128.dst_hi = dst_hi;
+ i->Pin.DfpQuantize128.dst_lo = dst_lo;
+ i->Pin.DfpQuantize128.src_hi = src_hi;
+ i->Pin.DfpQuantize128.src_lo = src_lo;
+ i->Pin.DfpQuantize128.rmc = rmc;
+ return i;
+}
PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
HReg src_hi, HReg src_lo ) {
PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
i->Pin.DfpI64StoD128.dst_lo = dst_lo;
return i;
}
+PPCInstr* PPCInstr_ExtractExpD128 ( PPCFpOp op, HReg dst,
+ HReg src_hi, HReg src_lo ) {
+ /* dst is used to pass the srcL argument */
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_ExtractExpD128;
+ i->Pin.ExtractExpD128.op = op;
+ i->Pin.ExtractExpD128.dst = dst;
+ i->Pin.ExtractExpD128.src_hi = src_hi;
+ i->Pin.ExtractExpD128.src_lo = src_lo;
+ return i;
+}
+PPCInstr* PPCInstr_InsertExpD128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
+ HReg srcL, HReg srcR_hi, HReg srcR_lo ) {
+ /* dst is used to pass the srcL argument */
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_InsertExpD128;
+ i->Pin.InsertExpD128.op = op;
+ i->Pin.InsertExpD128.dst_hi = dst_hi;
+ i->Pin.InsertExpD128.dst_lo = dst_lo;
+ i->Pin.InsertExpD128.srcL = srcL;
+ i->Pin.InsertExpD128.srcR_hi = srcR_hi;
+ i->Pin.InsertExpD128.srcR_lo = srcR_lo;
+ return i;
+}
+PPCInstr* PPCInstr_Dfp64Cmp (/* UInt crfD,*/ HReg dst, HReg srcL, HReg srcR ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_Dfp64Cmp;
+ i->Pin.Dfp64Cmp.dst = dst;
+ i->Pin.Dfp64Cmp.srcL = srcL;
+ i->Pin.Dfp64Cmp.srcR = srcR;
+ return i;
+}
+PPCInstr* PPCInstr_Dfp128Cmp ( HReg dst, HReg srcL_hi, HReg srcL_lo,
+ HReg srcR_hi, HReg srcR_lo ) {
+ PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
+ i->tag = Pin_Dfp128Cmp;
+ i->Pin.Dfp128Cmp.dst = dst;
+ i->Pin.Dfp128Cmp.srcL_hi = srcL_hi;
+ i->Pin.Dfp128Cmp.srcL_lo = srcL_lo;
+ i->Pin.Dfp128Cmp.srcR_hi = srcR_hi;
+ i->Pin.Dfp128Cmp.srcR_lo = srcR_lo;
+ return i;
+}
PPCInstr* PPCInstr_EvCheck ( PPCAMode* amCounter,
PPCAMode* amFailAddr ) {
PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
return i;
}
-
/*
Valid combo | fromI | int32 | syned | flt64 |
--------------------------------------------
ppPPCRI(i->Pin.DfpShift128.shift);
return;
+ case Pin_DfpRound:
+ vex_printf("drintx ");
+ ppHRegPPC(i->Pin.DfpRound.dst);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpRound.src);
+ vex_printf(",");
+ ppPPCRI(i->Pin.DfpRound.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
+ return;
+
+ case Pin_DfpRound128:
+ vex_printf("drintxq ");
+ ppHRegPPC(i->Pin.DfpRound128.dst_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpRound128.src_hi);
+ vex_printf(",");
+ ppPPCRI(i->Pin.DfpRound128.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
+ return;
+
+ case Pin_DfpQuantize:
+ vex_printf("%s ", showPPCFpOp(i->Pin.DfpQuantize.op));
+ ppHRegPPC(i->Pin.DfpQuantize.dst);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpQuantize.srcL);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpQuantize.srcR);
+ vex_printf(",");
+ ppPPCRI(i->Pin.DfpQuantize.rmc);
+ return;
+
+ case Pin_DfpQuantize128:
+ /* Dst is used to pass in left source and return result */
+ vex_printf("dquaq ");
+ ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.DfpQuantize128.src_hi);
+ vex_printf(",");
+ ppPPCRI(i->Pin.DfpQuantize128.rmc);
+ return;
+
case Pin_DfpD128toD64:
vex_printf("%s ", showPPCFpOp(i->Pin.DfpD128toD64.op));
ppHRegPPC(i->Pin.DfpD128toD64.dst);
ppHRegPPC(i->Pin.DfpI64StoD128.src);
vex_printf(",");
return;
-
+ case Pin_ExtractExpD128:
+ vex_printf("dxexq ");
+ ppHRegPPC(i->Pin.ExtractExpD128.dst);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.ExtractExpD128.src_hi);
+ return;
+ case Pin_InsertExpD128:
+ vex_printf("diexq ");
+ ppHRegPPC(i->Pin.InsertExpD128.dst_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.InsertExpD128.srcL);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.InsertExpD128.srcR_hi);
+ return;
+ case Pin_Dfp64Cmp:
+ vex_printf("dcmpo %%cr1,");
+ ppHRegPPC(i->Pin.Dfp64Cmp.srcL);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.Dfp64Cmp.srcR);
+ vex_printf("; mfcr ");
+ ppHRegPPC(i->Pin.Dfp64Cmp.dst);
+ vex_printf("; rlwinm ");
+ ppHRegPPC(i->Pin.Dfp64Cmp.dst);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.Dfp64Cmp.dst);
+ vex_printf(",8,28,31");
+ return;
+ case Pin_Dfp128Cmp:
+ vex_printf("dcmpoq %%cr1,");
+ ppHRegPPC(i->Pin.Dfp128Cmp.srcL_hi);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.Dfp128Cmp.srcR_hi);
+ vex_printf("; mfcr ");
+ ppHRegPPC(i->Pin.Dfp128Cmp.dst);
+ vex_printf("; rlwinm ");
+ ppHRegPPC(i->Pin.Dfp128Cmp.dst);
+ vex_printf(",");
+ ppHRegPPC(i->Pin.Dfp128Cmp.dst);
+ vex_printf(",8,28,31");
+ return;
case Pin_EvCheck:
/* Note that the counter dec is 32 bit even in 64-bit mode. */
vex_printf("(evCheck) ");
ppPPCAMode(i->Pin.EvCheck.amFailAddr);
vex_printf("; mtctr r30; bctr; nofail:");
return;
-
case Pin_ProfInc:
if (mode64) {
vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
vex_printf("lwz r29,0(r30); addze r29,r29; stw r29,0(r30)");
}
break;
-
default:
vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
vpanic("ppPPCInstr");
addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_hi);
addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_lo);
return;
+ case Pin_DfpRound:
+ addHRegUse(u, HRmWrite, i->Pin.DfpRound.dst);
+ addHRegUse(u, HRmRead, i->Pin.DfpRound.src);
+ return;
+ case Pin_DfpRound128:
+ addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_hi);
+ addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_lo);
+ addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_hi);
+ addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_lo);
+ return;
+ case Pin_DfpQuantize:
+ addRegUsage_PPCRI(u, i->Pin.DfpQuantize.rmc);
+ addHRegUse(u, HRmWrite, i->Pin.DfpQuantize.dst);
+ addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcL);
+ addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcR);
+ return;
+ case Pin_DfpQuantize128:
+ addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_hi);
+ addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_lo);
+ addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_hi);
+ addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_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.DfpI64StoD128.dst_hi);
addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_lo);
return;
+ case Pin_ExtractExpD128:
+ addHRegUse(u, HRmWrite, i->Pin.ExtractExpD128.dst);
+ addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_hi);
+ addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_lo);
+ return;
+ case Pin_InsertExpD128:
+ addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_hi);
+ addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_lo);
+ addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcL);
+ addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_hi);
+ addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_lo);
+ return;
+ case Pin_Dfp64Cmp:
+ addHRegUse(u, HRmWrite, i->Pin.Dfp64Cmp.dst);
+ addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcL);
+ addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcR);
+ return;
+ case Pin_Dfp128Cmp:
+ addHRegUse(u, HRmWrite, i->Pin.Dfp128Cmp.dst);
+ addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_hi);
+ addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_lo);
+ addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_hi);
+ addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_lo);
+ return;
case Pin_EvCheck:
/* We expect both amodes only to mention the GSP (r31), so this
is in fact pointless, since GSP isn't allocatable, but
mapReg(m, &i->Pin.DfpShift128.dst_hi);
mapReg(m, &i->Pin.DfpShift128.dst_lo);
return;
+ case Pin_DfpRound:
+ mapReg(m, &i->Pin.DfpRound.dst);
+ mapReg(m, &i->Pin.DfpRound.src);
+ return;
+ case Pin_DfpRound128:
+ mapReg(m, &i->Pin.DfpRound128.dst_hi);
+ mapReg(m, &i->Pin.DfpRound128.dst_lo);
+ mapReg(m, &i->Pin.DfpRound128.src_hi);
+ mapReg(m, &i->Pin.DfpRound128.src_lo);
+ return;
+ case Pin_DfpQuantize:
+ mapRegs_PPCRI(m, i->Pin.DfpQuantize.rmc);
+ mapReg(m, &i->Pin.DfpQuantize.dst);
+ mapReg(m, &i->Pin.DfpQuantize.srcL);
+ mapReg(m, &i->Pin.DfpQuantize.srcR);
+ return;
+ case Pin_DfpQuantize128:
+ mapRegs_PPCRI(m, i->Pin.DfpQuantize128.rmc);
+ mapReg(m, &i->Pin.DfpQuantize128.dst_hi);
+ mapReg(m, &i->Pin.DfpQuantize128.dst_lo);
+ mapReg(m, &i->Pin.DfpQuantize128.src_hi);
+ mapReg(m, &i->Pin.DfpQuantize128.src_lo);
case Pin_DfpD128toD64:
mapReg(m, &i->Pin.DfpD128toD64.src_hi);
mapReg(m, &i->Pin.DfpD128toD64.src_lo);
mapReg(m, &i->Pin.DfpI64StoD128.dst_hi);
mapReg(m, &i->Pin.DfpI64StoD128.dst_lo);
return;
+ case Pin_ExtractExpD128:
+ mapReg(m, &i->Pin.ExtractExpD128.dst);
+ mapReg(m, &i->Pin.ExtractExpD128.src_hi);
+ mapReg(m, &i->Pin.ExtractExpD128.src_lo);
+ return;
+ case Pin_InsertExpD128:
+ mapReg(m, &i->Pin.InsertExpD128.dst_hi);
+ mapReg(m, &i->Pin.InsertExpD128.dst_lo);
+ mapReg(m, &i->Pin.InsertExpD128.srcL);
+ mapReg(m, &i->Pin.InsertExpD128.srcR_hi);
+ mapReg(m, &i->Pin.InsertExpD128.srcR_lo);
+ return;
+ case Pin_Dfp64Cmp:
+ mapReg(m, &i->Pin.Dfp64Cmp.dst);
+ mapReg(m, &i->Pin.Dfp64Cmp.srcL);
+ mapReg(m, &i->Pin.Dfp64Cmp.srcR);
+ return;
+ case Pin_Dfp128Cmp:
+ mapReg(m, &i->Pin.Dfp128Cmp.dst);
+ mapReg(m, &i->Pin.Dfp128Cmp.srcL_hi);
+ mapReg(m, &i->Pin.Dfp128Cmp.srcL_lo);
+ mapReg(m, &i->Pin.Dfp128Cmp.srcR_hi);
+ mapReg(m, &i->Pin.Dfp128Cmp.srcR_lo);
+ return;
case Pin_EvCheck:
/* We expect both amodes only to mention the GSP (r31), so this
is in fact pointless, since GSP isn't allocatable, but
return emit32(p, theInstr);
}
+static UChar* mkFormZ23 ( UChar* p, UInt opc1, UInt r1, UInt r2,
+ UInt r3, UInt rmc, UInt opc2, UInt b0 )
+{
+ UInt theInstr;
+ vassert(opc1 < 0x40);
+ vassert(r1 < 0x20);
+ vassert(r2 < 0x20);
+ vassert(r3 < 0x20);
+ vassert(rmc < 0x4);
+ vassert(opc2 < 0x100);
+ vassert(b0 < 0x2);
+ theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
+ (r3<<11) | (rmc<<9) | (opc2<<1) | (b0));
+ return emit32(p, theInstr);
+}
+
static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
PPCAMode* am, Bool mode64 )
{
case Pfp_DCTFIX: // D64 to I64 conversion
p = mkFormX( p, 59, fr_dst, 0, fr_src, 290, 0);
break;
+ case Pfp_DXEX: // Extract exponent
+ p = mkFormX( p, 59, fr_dst, 0, fr_src, 354, 0 );
+ break;
default:
goto bad;
}
* mode from the Iop instruction. */
p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 546, 0 );
break;
+ case Pfp_DIEX: /* diex, insert exponent */
+ p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 866, 0 );
+ break;
default:
goto bad;
}
goto done;
}
+ case Pin_ExtractExpD128: {
+ UInt fr_dst = fregNo(i->Pin.ExtractExpD128.dst);
+ UInt fr_srcHi = fregNo(i->Pin.ExtractExpD128.src_hi);
+ UInt fr_srcLo = fregNo(i->Pin.ExtractExpD128.src_lo);
+
+ switch (i->Pin.ExtractExpD128.op) {
+ case Pfp_DXEXQ:
+ /* Setup the upper and lower registers of the source operand
+ * register pair.
+ */
+ p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0);
+ p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0);
+ p = mkFormX( p, 63, 10, 0, 12, 354, 0 );
+
+ /* The instruction will put the 64-bit result in
+ * register 10.
+ */
+ p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0);
+ break;
+ default:
+ vex_printf("Error: emit_PPCInstr case Pin_DfpExtractExp, case inst Default\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);
goto done;
}
+ case Pin_DfpRound: {
+ UInt fr_dst = fregNo(i->Pin.DfpRound.dst);
+ UInt fr_src = fregNo(i->Pin.DfpRound.src);
+ UInt r_rmc, r, rmc;
+
+ r_rmc = i->Pin.DfpRound.r_rmc->Pri.Imm;
+ r = (r_rmc & 0x8) >> 3;
+ rmc = r_rmc & 0x3;
+
+ // drintx
+ p = mkFormZ23(p, 59, fr_dst, r, fr_src, rmc, 99, 0);
+ goto done;
+ }
+
+ case Pin_DfpRound128: {
+ UInt fr_dstHi = fregNo(i->Pin.DfpRound128.dst_hi);
+ UInt fr_dstLo = fregNo(i->Pin.DfpRound128.dst_lo);
+ UInt fr_srcHi = fregNo(i->Pin.DfpRound128.src_hi);
+ UInt fr_srcLo = fregNo(i->Pin.DfpRound128.src_lo);
+ UInt r_rmc, r, rmc;
+
+ r_rmc = i->Pin.DfpRound128.r_rmc->Pri.Imm;
+ r = (r_rmc & 0x8) >> 3;
+ rmc = r_rmc & 0x3;
+
+ /* Setup the upper and lower registers of the source operand
+ * register pair.
+ */
+ p = mkFormX(p, 63, 12, 0, fr_srcHi, 72, 0);
+ p = mkFormX(p, 63, 13, 0, fr_srcLo, 72, 0);
+
+ /* Do drintx instruction with 128-bit source operands in
+ * registers (12,13).
+ */
+ p = mkFormZ23(p, 63, 10, r, 12, rmc, 99, 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);
+ goto done;
+ }
+
+ case Pin_DfpQuantize: {
+ UInt fr_dst = fregNo(i->Pin.DfpQuantize.dst);
+ UInt fr_srcL = fregNo(i->Pin.DfpQuantize.srcL);
+ UInt fr_srcR = fregNo(i->Pin.DfpQuantize.srcR);
+ UInt rmc;
+
+ rmc = i->Pin.DfpQuantize.rmc->Pri.Imm;
+
+ switch (i->Pin.DfpQuantize.op) {
+ case Pfp_DQUA:
+ p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 3, 0);
+ break;
+ case Pfp_RRDTR:
+ p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 35, 0);
+ break;
+ default:
+ break;
+ }
+ goto done;
+ }
+
+ case Pin_DfpQuantize128: {
+ UInt fr_dst_hi = fregNo(i->Pin.DfpQuantize128.dst_hi);
+ UInt fr_dst_lo = fregNo(i->Pin.DfpQuantize128.dst_lo);
+ UInt fr_src_hi = fregNo(i->Pin.DfpQuantize128.src_hi);
+ UInt fr_src_lo = fregNo(i->Pin.DfpQuantize128.src_lo);
+ UInt rmc;
+
+ rmc = i->Pin.DfpQuantize128.rmc->Pri.Imm;
+ /* Setup the upper and lower registers of the source operand
+ * register pairs. Note, left source operand passed in via the
+ * dst register pair.
+ */
+ p = mkFormX(p, 63, 10, 0, fr_dst_hi, 72, 0);
+ p = mkFormX(p, 63, 11, 0, fr_dst_lo, 72, 0);
+ p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0);
+ p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0);
+
+ /* Do dquaq instruction with 128-bit source operands in
+ * registers (12,13).
+ */
+ switch (i->Pin.DfpQuantize128.op) {
+ case Pfp_DQUAQ:
+ p = mkFormZ23(p, 63, 10, 10, 12, rmc, 3, 0);
+ break;
+ case Pfp_DRRNDQ:
+ p = mkFormZ23(p, 63, 10, 10, 12, rmc, 35, 0);
+ break;
+ default:
+ vpanic("Pin_DfpQuantize128: default case, couldn't find inst to issue \n");
+ break;
+ }
+
+ /* 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_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 );
goto done;
}
+ case Pin_InsertExpD128: {
+ UInt fr_dstHi = fregNo(i->Pin.InsertExpD128.dst_hi);
+ UInt fr_dstLo = fregNo(i->Pin.InsertExpD128.dst_lo);
+ UInt fr_srcL = fregNo(i->Pin.InsertExpD128.srcL);
+ UInt fr_srcRHi = fregNo(i->Pin.InsertExpD128.srcR_hi);
+ UInt fr_srcRLo = fregNo(i->Pin.InsertExpD128.srcR_lo);
+
+ /* The left operand is a single F64 value, the right is an F128
+ * register pair.
+ */
+ p = mkFormX(p, 63, 10, 0, fr_srcL, 72, 0);
+ p = mkFormX(p, 63, 12, 0, fr_srcRHi, 72, 0);
+ p = mkFormX(p, 63, 13, 0, fr_srcRLo, 72, 0);
+ p = mkFormX(p, 63, 10, 10, 12, 866, 0 );
+
+ /* The instruction will put the 128-bit result into
+ * 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);
+ goto done;
+ }
+
+ case Pin_Dfp64Cmp:{
+ UChar crfD = 1;
+ UInt r_dst = iregNo(i->Pin.Dfp64Cmp.dst, mode64);
+ UInt fr_srcL = fregNo(i->Pin.Dfp64Cmp.srcL);
+ UInt fr_srcR = fregNo(i->Pin.Dfp64Cmp.srcR);
+ vassert(crfD < 8);
+ // dcmpo, dcmpu
+ p = mkFormX(p, 59, crfD<<2, fr_srcL, fr_srcR, 130, 0);
+
+ // mfcr (mv CR to r_dst)
+ p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
+
+ // rlwinm r_dst,r_dst,8,28,31
+ // => rotate field 1 to bottomw of word, masking out upper 28
+ p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
+ goto done;
+ }
+
+ case Pin_Dfp128Cmp: {
+ UChar crfD = 1;
+ UInt r_dst = iregNo(i->Pin.Dfp128Cmp.dst, mode64);
+ UInt fr_srcL_hi = fregNo(i->Pin.Dfp128Cmp.srcL_hi);
+ UInt fr_srcL_lo = fregNo(i->Pin.Dfp128Cmp.srcL_lo);
+ UInt fr_srcR_hi = fregNo(i->Pin.Dfp128Cmp.srcR_hi);
+ UInt fr_srcR_lo = fregNo(i->Pin.Dfp128Cmp.srcR_lo);
+ vassert(crfD < 8);
+ // dcmpoq, dcmpuq
+ /* Setup the upper and lower registers of the source operand
+ * register pair.
+ */
+ p = mkFormX(p, 63, 10, 0, fr_srcL_hi, 72, 0);
+ p = mkFormX(p, 63, 11, 0, fr_srcL_lo, 72, 0);
+ p = mkFormX(p, 63, 12, 0, fr_srcR_hi, 72, 0);
+ p = mkFormX(p, 63, 13, 0, fr_srcR_lo, 72, 0);
+
+ p = mkFormX(p, 63, crfD<<2, 10, 12, 130, 0);
+
+ // mfcr (mv CR to r_dst)
+ p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
+
+ // rlwinm r_dst,r_dst,8,28,31
+ // => rotate field 1 to bottomw of word, masking out upper 28
+ p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
+ goto done;
+ }
+
case Pin_EvCheck: {
/* This requires a 32-bit dec/test in both 32- and 64-bit
modes. */
/* Binary */
Pfp_ADDD, Pfp_SUBD, Pfp_MULD, Pfp_DIVD,
Pfp_ADDS, Pfp_SUBS, Pfp_MULS, Pfp_DIVS,
- Pfp_DRSP, Pfp_DCTFIX, Pfp_DCTFIXQ, Pfp_DCFFIX,
+ Pfp_DRSP, Pfp_DRDPQ, Pfp_DCTFIX, Pfp_DCTFIXQ, Pfp_DCFFIX,
+ Pfp_DQUA, Pfp_RRDTR, Pfp_DIEX, Pfp_DIEXQ,
/* Unary */
Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV, Pfp_RES, Pfp_RSQRTE,
Pfp_FRIN, Pfp_FRIM, Pfp_FRIP, Pfp_FRIZ,
- Pfp_DSCLI, Pfp_DSCRI, Pfp_DSCLIQ, Pfp_DSCRIQ, Pfp_DCTDP, Pfp_DCTQPQ,
- Pfp_DRDPQ, Pfp_DCFFIXQ
+ Pfp_DSCLI, Pfp_DSCRI, Pfp_DSCLIQ, Pfp_DSCRIQ, Pfp_DCTDP,
+ Pfp_DCTQPQ, Pfp_DCFFIXQ, Pfp_DXEX, Pfp_DXEXQ,
+
}
PPCFpOp;
* immediate value */
Pin_DfpD128toD64, /* DFP 128 to DFP 64 op */
Pin_DfpI64StoD128, /* DFP signed integer to DFP 128 */
+ Pin_DfpRound, /* D64 round to D64 */
+ Pin_DfpRound128, /* D128 round to D128 */
+ Pin_ExtractExpD128, /* DFP, extract 64 bit exponent */
+ Pin_InsertExpD128, /* DFP, insert 64 bit exponent and 128 bit binary
+ * significand into a DFP 128-bit value*/
+ Pin_Dfp64Cmp, /* DFP 64-bit compare, generating value into
+ * int reg */
+ Pin_Dfp128Cmp, /* DFP 128-bit compare, generating value into
+ * int reg */
+ Pin_DfpQuantize, /* D64 quantize using register value, significance
+ * round */
+ Pin_DfpQuantize128, /* D128 quantize using register value, significance
+ * round */
Pin_EvCheck, /* Event check */
Pin_ProfInc /* 64-bit profile counter increment */
}
HReg src_lo;
PPCRI* shift;
} DfpShift128;
+ struct {
+ HReg dst;
+ HReg src;
+ PPCRI* r_rmc;
+ } DfpRound;
+ struct {
+ HReg dst_hi;
+ HReg dst_lo;
+ HReg src_hi;
+ HReg src_lo;
+ PPCRI* r_rmc;
+ } DfpRound128;
+ struct {
+ PPCFpOp op;
+ HReg dst;
+ HReg srcL;
+ HReg srcR;
+ PPCRI* rmc;
+ } DfpQuantize;
+ struct {
+ PPCFpOp op;
+ HReg dst_hi;
+ HReg dst_lo;
+ HReg src_hi;
+ HReg src_lo;
+ PPCRI* rmc;
+ } DfpQuantize128;
+ struct {
+ PPCFpOp op;
+ HReg dst;
+ HReg src_hi;
+ HReg src_lo;
+ } ExtractExpD128;
+ struct {
+ PPCFpOp op;
+ HReg dst_hi;
+ HReg dst_lo;
+ HReg srcL;
+ HReg srcR_hi;
+ HReg srcR_lo;
+ } InsertExpD128;
struct {
PPCFpOp op;
HReg dst;
HReg dst_lo;
HReg src;
} DfpI64StoD128;
+ struct {
+ UChar crfD;
+ HReg dst;
+ HReg srcL;
+ HReg srcR;
+ } Dfp64Cmp;
+ struct {
+ UChar crfD;
+ HReg dst;
+ HReg srcL_hi;
+ HReg srcL_lo;
+ HReg srcR_hi;
+ HReg srcR_lo;
+ } Dfp128Cmp;
struct {
PPCAMode* amCounter;
PPCAMode* amFailAddr;
extern PPCInstr* PPCInstr_Dfp64Binary ( PPCFpOp op, HReg dst, HReg srcL,
HReg srcR );
extern PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src,
- PPCRI* shift );
+ 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,
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 PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
+ HReg dst_lo, HReg src);
+extern PPCInstr* PPCInstr_DfpRound ( HReg dst, HReg src, PPCRI* r_rmc );
+extern PPCInstr* PPCInstr_DfpRound128 ( HReg dst_hi, HReg dst_lo, HReg src_hi,
+ HReg src_lo, PPCRI* r_rmc );
+extern PPCInstr* PPCInstr_DfpQuantize ( PPCAvFpOp op, HReg dst, HReg srcL,
+ HReg srcR, PPCRI* rmc );
+extern PPCInstr* PPCInstr_DfpQuantize128 ( PPCAvFpOp op, HReg dst_hi,
+ HReg dst_lo,
+ HReg src_hi,
+ HReg src_lo, PPCRI* rmc );
+extern PPCInstr* PPCInstr_ExtractExpD128 ( PPCFpOp op, HReg dst,
+ HReg src_hi, HReg src_lo );
+extern PPCInstr* PPCInstr_InsertExpD128 ( PPCFpOp op, HReg dst_hi,
+ HReg dst_lo, HReg srcL,
+ HReg srcR_hi, HReg srcR_lo );
+extern PPCInstr* PPCInstr_Dfp64Cmp ( HReg dst, HReg srcL, HReg srcR );
+extern PPCInstr* PPCInstr_Dfp128Cmp ( HReg dst, HReg srcL_hi, HReg srcL_lo,
+ HReg srcR_hi, HReg srcR_lo );
extern PPCInstr* PPCInstr_EvCheck ( PPCAMode* amCounter,
PPCAMode* amFailAddr );
extern PPCInstr* PPCInstr_ProfInc ( void );
return r_dst;
}
- if (e->Iex.Binop.op == Iop_CmpF64) {
- HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
- HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
+ if ((e->Iex.Binop.op == Iop_CmpF64) |
+ (e->Iex.Binop.op == Iop_CmpD64) |
+ (e->Iex.Binop.op == Iop_CmpD128)) {
+ HReg fr_srcL;
+ HReg fr_srcL_lo;
+ HReg fr_srcR;
+ HReg fr_srcR_lo;
HReg r_ccPPC = newVRegI(env);
HReg r_ccIR = newVRegI(env);
HReg r_ccIR_b2 = newVRegI(env);
HReg r_ccIR_b6 = newVRegI(env);
- addInstr(env, PPCInstr_FpCmp(r_ccPPC, fr_srcL, fr_srcR));
+ if (e->Iex.Binop.op == Iop_CmpF64) {
+ fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
+ fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_FpCmp(r_ccPPC, fr_srcL, fr_srcR));
+
+ } else if (e->Iex.Binop.op == Iop_CmpD64) {
+ fr_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1);
+ fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_Dfp64Cmp(r_ccPPC, fr_srcL, fr_srcR));
+
+ } else { // e->Iex.Binop.op == Iop_CmpD128
+ iselDfp128Expr(&fr_srcL, &fr_srcL_lo, env, e->Iex.Binop.arg1);
+ iselDfp128Expr(&fr_srcR, &fr_srcR_lo, env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_Dfp128Cmp(r_ccPPC, fr_srcL, fr_srcL_lo,
+ fr_srcR, fr_srcR_lo));
+ }
/* Map compare result from PPC to IR,
conforming to CmpF64 definition. */
addInstr(env, PPCInstr_FpBinary(fpop, r_dst, r_srcL, r_srcR));
return r_dst;
}
+ switch (e->Iex.Triop.op) {
+ case Iop_QuantizeD64: fpop = Pfp_DQUA; break;
+ case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
+ default: break;
+ }
+ if (fpop != Pfp_INVALID) {
+ HReg r_dst = newVRegF(env);
+ HReg r_srcL = iselDblExpr(env, e->Iex.Triop.arg2);
+ HReg r_srcR = iselDblExpr(env, e->Iex.Triop.arg3);
+ PPCRI* rmc = iselWordExpr_RI(env, e->Iex.Triop.arg1);
+
+ // will set TE and RMC when issuing instruction
+ addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR, rmc));
+ return r_dst;
+ }
}
if (e->tag == Iex_Binop) {
PPCFpOp fpop = Pfp_INVALID;
switch (e->Iex.Binop.op) {
- case Iop_SqrtF64: fpop = Pfp_SQRT; break;
- default: break;
+ case Iop_SqrtF64: fpop = Pfp_SQRT; 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);
case Iop_RoundF64toF64_PosINF: fpop = Pfp_FRIP; break;
case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
case Iop_RoundF64toF64_ZERO: fpop = Pfp_FRIZ; break;
+ case Iop_ExtractExpD64: fpop = Pfp_DXEX; break;
default: break;
}
if (fpop != Pfp_INVALID) {
}
if (e->tag == Iex_Unop) {
- if (e->Iex.Binop.op == Iop_D32toD64) {
- HReg fr_dst = newVRegF(env);
+ HReg fr_dst = newVRegF(env);
+ switch (e->Iex.Unop.op) {
+ case Iop_ReinterpI64asD64: {
+ /* Given an I64, produce an IEEE754 DFP with the same
+ bit pattern. */
+ if (!mode64) {
+ HReg r_srcHi, r_srcLo;
+ iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
+ return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
+ } else {
+ HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+ return mk_LoadR64toFPR( env, r_src );
+ }
+ }
+
+ case Iop_ExtractExpD64: {
HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
- addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
+
+ addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, fr_dst, fr_src));
return fr_dst;
}
- }
+ case Iop_ExtractExpD128: {
+ /* Result is a D64 */
+ HReg r_srcHi;
+ HReg r_srcLo;
- if (e->tag == Iex_Unop) {
- switch (e->Iex.Unop.op) {
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
+ addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, fr_dst,
+ r_srcHi, r_srcLo));
+ return fr_dst;
+ }
+ case Iop_D32toD64: {
+ HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
+ addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
+ return fr_dst;
+ }
case Iop_D128HItoD64:
iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg );
return r_dstHi;
case Iop_D128LOtoD64:
iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg );
return r_dstLo;
+ case Iop_InsertExpD64: {
+ HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
+ HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
+
+ addInstr(env, PPCInstr_Dfp64Binary(Pfp_DIEX, fr_dst, fr_srcL,
+ fr_srcR));
+ return fr_dst;
+ }
default:
vex_printf( "ERROR: iselDfp64Expr_wrk, UNKNOWN unop case %d\n",
e->Iex.Unop.op );
}
}
- 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) {
default:
break;
}
+
+ if (e->Iex.Unop.op == Iop_RoundD64toInt) {
+ HReg fr_dst = newVRegF(env);
+ HReg fr_src = newVRegF(env);
+ PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1);
+
+ fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_DfpRound(fr_dst, fr_src, r_rmc));
+ return fr_dst;
+ }
}
if (e->tag == Iex_Binop) {
PPCFpOp fpop = Pfp_INVALID;
+ HReg fr_dst = newVRegF(env);
+
switch (e->Iex.Binop.op) {
case Iop_D64toD32: fpop = Pfp_DRSP; break;
case Iop_I64StoD64: fpop = Pfp_DCFFIX; 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;
}
+
+ 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_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;
+ }
+
+ switch (e->Iex.Binop.op) {
+ case Iop_InsertExpD64:
+ fpop = Pfp_DIEX;
+ break;
+ default: break;
+ }
+ if (fpop != Pfp_INVALID) {
+ HReg fr_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1);
+ HReg fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_Dfp64Binary(fpop, fr_dst, fr_srcL, fr_srcR));
+ return fr_dst;
+ }
}
if (e->tag == Iex_Triop) {
addInstr( env, PPCInstr_Dfp64Binary( fpop, r_dst, r_srcL, r_srcR ) );
return r_dst;
}
+
+ switch (e->Iex.Triop.op) {
+ case Iop_QuantizeD64: fpop = Pfp_DQUA; break;
+ case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
+ default: break;
+ }
+ if (fpop != Pfp_INVALID) {
+ HReg r_dst = newVRegF(env);
+ HReg r_srcL = iselDfp64Expr(env, e->Iex.Triop.arg2);
+ HReg r_srcR = iselDfp64Expr(env, e->Iex.Triop.arg3);
+ PPCRI* rmc = iselWordExpr_RI(env, e->Iex.Triop.arg1);
+
+ addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR,
+ rmc));
+ return r_dst;
+ }
}
ppIRExpr( e );
/* read 128-bit IRTemp */
if (e->tag == Iex_RdTmp) {
- // lookupDfp128IRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp );
lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp );
return;
}
*rHi = fr_dst_hi;
*rLo = fr_dst_lo;
- return;
+ return;
+ }
+ case Iop_RoundD128toInt: {
+ HReg r_dstHi = newVRegF(env);
+ HReg r_dstLo = newVRegF(env);
+ PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1);
+
+ // will set R and RMC when issuing instruction
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
+
+ addInstr(env, PPCInstr_DfpRound128(r_dstHi, r_dstLo,
+ r_srcHi, r_srcLo, r_rmc));
+ *rHi = r_dstHi;
+ *rLo = r_dstLo;
+ return;
+ }
+ case Iop_InsertExpD128: {
+ HReg r_dstHi = newVRegF(env);
+ HReg r_dstLo = newVRegF(env);
+ HReg r_srcL = newVRegF(env);
+
+ r_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1);
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
+ addInstr(env, PPCInstr_InsertExpD128(Pfp_DIEXQ,
+ r_dstHi, r_dstLo,
+ r_srcL, r_srcHi, r_srcLo));
+ *rHi = r_dstHi;
+ *rLo = r_dstLo;
+ return;
}
default:
- vex_printf( "ERROR: iselD128Expr_wrk, UNKNOWN binop case %d\n",
+ vex_printf( "ERROR: iselDfp128Expr_wrk, UNKNOWN binop case %d\n",
e->Iex.Binop.op );
break;
}
*rLo = r_dstLo;
return;
}
+ switch (e->Iex.Triop.op) {
+ case Iop_QuantizeD128: fpop = Pfp_DQUAQ; break;
+ case Iop_SignificanceRoundD128: fpop = Pfp_DRRNDQ; break;
+ default: break;
+ }
+ if (fpop != Pfp_INVALID) {
+ HReg r_dstHi = newVRegF(env);
+ HReg r_dstLo = newVRegF(env);
+ HReg r_srcHi = newVRegF(env);
+ HReg r_srcLo = newVRegF(env);
+ PPCRI* rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1);
+
+ /* dst will be used to pass in the left operand and get the result */
+ iselDfp128Expr(&r_dstHi, &r_dstLo, env, e->Iex.Triop.arg2);
+ iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Triop.arg3);
+
+ // will set RMC when issuing instruction
+ addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
+ r_srcHi, r_srcLo, rmc));
+ *rHi = r_dstHi;
+ *rLo = r_dstLo;
+ return;
+ }
}
ppIRExpr( e );
case Iop_DivD128: vex_printf("DivD128"); return;
case Iop_ShlD128: vex_printf("ShlD128"); return;
case Iop_ShrD128: vex_printf("ShrD128"); return;
+ case Iop_RoundD64toInt: vex_printf("Iop_RoundD64toInt"); return;
+ case Iop_RoundD128toInt: vex_printf("Iop_RoundD128toInt"); return;
+ case Iop_QuantizeD64: vex_printf("Iop_QuantizeD64"); return;
+ case Iop_QuantizeD128: vex_printf("Iop_QuantizeD128"); return;
+ case Iop_ExtractExpD64: vex_printf("Iop_ExtractExpD64"); return;
+ case Iop_ExtractExpD128: vex_printf("Iop_ExtractExpD128"); return;
+ case Iop_InsertExpD64: vex_printf("Iop_InsertExpD64"); return;
+ case Iop_InsertExpD128: vex_printf("Iop_InsertExpD128"); return;
+ case Iop_CmpD64: vex_printf("CmpD64"); return;
+ case Iop_CmpD128: vex_printf("CmpD128"); return;
case Iop_D64HLtoD128: vex_printf("D64HLtoD128"); return;
case Iop_D128HItoD64: vex_printf("D128HItoD64"); return;
case Iop_D128LOtoD64: vex_printf("D128LOtoD64"); return;
-
+ case Iop_SignificanceRoundD64: vex_printf("Iop_SignificanceRoundD64");
+ return;
+ case Iop_SignificanceRoundD128: vex_printf("Iop_SignificanceRoundD128");
+ return;
+ case Iop_ReinterpI64asD64: vex_printf("ReinterpI64asD64"); return;
default: vpanic("ppIROp(1)");
}
case Iop_F128toF64: BINARY(ity_RMode,Ity_F128, Ity_F64);
case Iop_D32toD64:
+ case Iop_ExtractExpD64:
UNARY(Ity_D64, Ity_D64);
+ case Iop_InsertExpD64:
+ BINARY(Ity_D64,Ity_D64, Ity_D64);
+
+ case Iop_ExtractExpD128:
+ UNARY(Ity_D128, Ity_D64);
+
+ case Iop_InsertExpD128:
+ BINARY(Ity_D64,Ity_D128, Ity_D128);
+
case Iop_D64toD128:
UNARY(Ity_D64, Ity_D128);
+ case Iop_ReinterpI64asD64:
+ UNARY(Ity_I64, Ity_D64);
+
+ case Iop_RoundD64toInt:
+ BINARY(ity_RMode,Ity_D64, Ity_D64);
+
+ case Iop_RoundD128toInt:
+ BINARY(ity_RMode,Ity_D128, Ity_D128);
+
case Iop_I64StoD128: /* I64 bit pattern stored in Float register */
UNARY(Ity_D64, Ity_D128);
case Iop_I64StoD64: /* I64 bit pattern stored in Float register */
BINARY(ity_RMode, Ity_D64, Ity_D64);
+ case Iop_CmpD64:
+ BINARY(Ity_D64,Ity_D64, Ity_I32);
+
+ case Iop_CmpD128:
+ BINARY(Ity_D128,Ity_D128, Ity_I32);
+
+ case Iop_QuantizeD64:
+ case Iop_SignificanceRoundD64:
+ TERNARY(ity_RMode,Ity_D64,Ity_D64, Ity_D64);
+
+ case Iop_QuantizeD128:
+ case Iop_SignificanceRoundD128:
+ TERNARY(ity_RMode,Ity_D128,Ity_D128, Ity_D128);
+
case Iop_ShlD128:
case Iop_ShrD128:
BINARY(Ity_D128, Ity_I8, Ity_D128 );
/* ARITHMETIC INSTRUCTIONS 64-bit
----------------------------------
IRRoundingModeDFP(I32) X D64 X D64 -> D64
- Iop_AddD64, Iop_SubD64, Iop_MulD64, Iop_DivD64
*/
Iop_AddD64, Iop_SubD64, Iop_MulD64, Iop_DivD64,
/* ARITHMETIC INSTRUCTIONS 128-bit
----------------------------------
IRRoundingModeDFP(I32) X D128 X D128 -> D128
- Iop_AddD128, Iop_SubD128, Iop_MulD128, Iop_DivD128
*/
Iop_AddD128, Iop_SubD128, Iop_MulD128, Iop_DivD128,
* 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 */
+ *
+ * D64 x U8 -> D64 left shift and right shift respectively */
Iop_ShlD64, Iop_ShrD64,
/* D128 x U8 -> D128 left shift and right shift respectively */
/* IRRoundingModeDFP(I32) x D128 -> I64 */
Iop_D128toI64S,
+ /* ROUNDING INSTRUCTIONS
+ * IRRoundingMode(I32) x D64 -> D64
+ * The D64 operand, if a finite number, is rounded to an integer value.
+ */
+ Iop_RoundD64toInt,
+
+ /* IRRoundingMode(I32) x D128 -> D128 */
+ Iop_RoundD128toInt,
+
+ /* COMPARE INSTRUCTIONS
+ * D64 x D64 -> IRCmpD64Result(I32) */
+ Iop_CmpD64,
+
+ /* D128 x D128 -> IRCmpD64Result(I32) */
+ Iop_CmpD128,
+
+ /* QUANTIZE AND ROUND INSTRUCTIONS
+ * The source operand is converted and rounded to the form with the
+ * immediate exponent specified by the rounding and exponent parameter.
+ *
+ * The second operand is converted and rounded to the form
+ * of the first operand's exponent and the rounded based on the specified
+ * rounding mode parameter.
+ *
+ * IRRoundingModeDFP(I32) x D64 x D64-> D64 */
+ Iop_QuantizeD64,
+
+ /* IRRoundingModeDFP(I32) x D128 x D128 -> D128 */
+ Iop_QuantizeD128,
+
+ /* IRRoundingModeDFP(I32) x I8 x D64 -> D64
+ * The Decimal Floating point operand is rounded to the requested
+ * significance given by the I8 operand as specified by the rounding
+ * mode.
+ */
+ Iop_SignificanceRoundD64,
+
+ /* IRRoundingModeDFP(I32) x I8 x D128 -> D128 */
+ Iop_SignificanceRoundD128,
+
+ /* EXTRACT AND INSERT INSTRUCTIONS
+ * D64 -> I64
+ * The exponent of the D32 or D64 operand is extracted. The
+ * extracted exponent is converted to a 64-bit signed binary integer.
+ */
+ Iop_ExtractExpD64,
+
+ /* D128 -> I64 */
+ Iop_ExtractExpD128,
+
+ /* I64 x I64 -> D64
+ * The exponent is specified by the first I64 operand the signed
+ * significand is given by the second I64 value. The result is a D64
+ * value consisting of the specified significand and exponent whose
+ * sign is that of the specified significand.
+ */
+ Iop_InsertExpD64,
+
+ /* I64 x I128 -> D128 */
+ Iop_InsertExpD128,
+
/* Support for 128-bit DFP type */
Iop_D64HLtoD128, Iop_D128HItoD64, Iop_D128LOtoD64,
+ /* Conversion I64 -> D64 */
+ Iop_ReinterpI64asD64,
+
/* ------------------ 128-bit SIMD FP. ------------------ */
/* --- 32x4 vector FP --- */