|
[Valgrind-developers] vex: r2312: POWER Processor decimal floating
point instruction support, part 3
From: <sv...@va...> - 2012-04-23 11:21:26
|
sewardj 2012-04-23 12:21:12 +0100 (Mon, 23 Apr 2012)
New Revision: 2312
Log:
POWER Processor decimal floating point instruction support, part 3
(Carl Love, ca...@us...). Bug 298080.
Modified files:
trunk/priv/guest_ppc_toIR.c
trunk/priv/host_generic_regs.h
trunk/priv/host_ppc_defs.c
trunk/priv/host_ppc_defs.h
trunk/priv/host_ppc_isel.c
trunk/priv/ir_defs.c
trunk/pub/libvex_ir.h
Modified: trunk/priv/guest_ppc_toIR.c (+490 -1)
===================================================================
--- trunk/priv/guest_ppc_toIR.c 2012-04-23 10:48:14 +01:00 (rev 2311)
+++ trunk/priv/guest_ppc_toIR.c 2012-04-23 12:21:12 +01:00 (rev 2312)
@@ -254,6 +254,11 @@
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 );
@@ -8811,6 +8816,418 @@
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 ---*/
/*------------------------------------------------------------*/
@@ -13999,6 +14416,13 @@
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
@@ -14013,6 +14437,13 @@
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;
@@ -14036,6 +14467,28 @@
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 */
@@ -14249,7 +14702,22 @@
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
case 0x122: // dctfixq - DFP convert to fixed quad
@@ -14332,9 +14800,30 @@
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:
Modified: trunk/pub/libvex_ir.h (+66 -4)
===================================================================
--- trunk/pub/libvex_ir.h 2012-04-23 10:48:14 +01:00 (rev 2311)
+++ trunk/pub/libvex_ir.h 2012-04-23 12:21:12 +01:00 (rev 2312)
@@ -991,14 +991,12 @@
/* 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,
@@ -1008,8 +1006,8 @@
* 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 */
@@ -1042,9 +1040,73 @@
/* 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 --- */
Modified: trunk/priv/host_ppc_isel.c (+191 -35)
===================================================================
--- trunk/priv/host_ppc_isel.c 2012-04-23 10:48:14 +01:00 (rev 2311)
+++ trunk/priv/host_ppc_isel.c 2012-04-23 12:21:12 +01:00 (rev 2312)
@@ -1497,9 +1497,13 @@
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);
@@ -1507,8 +1511,23 @@
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. */
/*
@@ -3417,13 +3436,30 @@
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);
@@ -3512,6 +3548,7 @@
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) {
@@ -3633,22 +3670,56 @@
}
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_DXEX, fr_dst, fr_src));
+ return fr_dst;
+ }
+ case Iop_ExtractExpD128: {
+ /* Result is a D64 */
+ HReg r_srcHi;
+ HReg r_srcLo;
+
+ 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;
}
- }
-
- if (e->tag == Iex_Unop) {
- switch (e->Iex.Unop.op) {
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 );
@@ -3656,27 +3727,8 @@
}
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);
@@ -3703,10 +3755,22 @@
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;
@@ -3714,12 +3778,38 @@
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) {
@@ -3750,6 +3840,22 @@
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 );
@@ -3771,7 +3877,6 @@
/* 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;
}
@@ -3849,10 +3954,38 @@
*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;
}
@@ -3894,6 +4027,29 @@
*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 );
Modified: trunk/priv/host_generic_regs.h (+1 -1)
===================================================================
--- trunk/priv/host_generic_regs.h 2012-04-23 10:48:14 +01:00 (rev 2311)
+++ trunk/priv/host_generic_regs.h 2012-04-23 12:21:12 +01:00 (rev 2312)
@@ -188,7 +188,7 @@
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 {
Modified: trunk/priv/ir_defs.c (+48 -1)
===================================================================
--- trunk/priv/ir_defs.c 2012-04-23 10:48:14 +01:00 (rev 2311)
+++ trunk/priv/ir_defs.c 2012-04-23 12:21:12 +01:00 (rev 2312)
@@ -957,10 +957,24 @@
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)");
}
@@ -2625,11 +2639,30 @@
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);
@@ -2654,6 +2687,20 @@
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 );
Modified: trunk/priv/host_ppc_defs.h (+93 -6)
===================================================================
--- trunk/priv/host_ppc_defs.h 2012-04-23 10:48:14 +01:00 (rev 2311)
+++ trunk/priv/host_ppc_defs.h 2012-04-23 12:21:12 +01:00 (rev 2312)
@@ -370,13 +370,15 @@
/* 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;
@@ -505,6 +507,19 @@
* 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 */
}
@@ -864,7 +879,48 @@
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 src_hi;
HReg src_lo;
@@ -876,6 +932,20 @@
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;
} EvCheck;
@@ -951,7 +1021,7 @@
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,
@@ -961,8 +1031,25 @@
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 );
Modified: trunk/priv/host_ppc_defs.c (+490 -5)
===================================================================
--- trunk/priv/host_ppc_defs.c 2012-04-23 10:48:14 +01:00 (rev 2311)
+++ trunk/priv/host_ppc_defs.c 2012-04-23 12:21:12 +01:00 (rev 2312)
@@ -644,7 +644,13 @@
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");
}
}
@@ -1067,6 +1073,49 @@
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));
@@ -1087,6 +1136,49 @@
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));
@@ -1101,7 +1193,6 @@
return i;
}
-
/*
Valid combo | fromI | int32 | syned | flt64 |
--------------------------------------------
@@ -1919,6 +2010,47 @@
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);
@@ -1934,7 +2066,46 @@
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) ");
@@ -1947,7 +2118,6 @@
ppPPCAMode(i->Pin.EvCheck.amFailAddr);
vex_printf("; mtctr r30; bctr; nofail:");
return;
-
case Pin_ProfInc:
if (mode64) {
vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
@@ -1958,7 +2128,6 @@
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");
@@ -2256,6 +2425,28 @@
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);
@@ -2273,6 +2464,30 @@
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
@@ -2521,6 +2736,28 @@
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);
@@ -2531,6 +2768,30 @@
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
@@ -2901,6 +3162,22 @@
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 )
{
@@ -4671,6 +4948,9 @@
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;
}
@@ -4698,6 +4978,9 @@
* 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;
}
@@ -4725,6 +5008,31 @@
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_...
[truncated message content] |