From: Julian Seward Date: Mon, 23 Apr 2012 11:21:12 +0000 (+0000) Subject: POWER Processor decimal floating point instruction support, part 3 X-Git-Tag: svn/VALGRIND_3_8_1^2~166 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc059f33781249b2886b842bb3e0a3ba1c5878c1;p=thirdparty%2Fvalgrind.git POWER Processor decimal floating point instruction support, part 3 (Carl Love, carll@us.ibm.com). Bug 298080. git-svn-id: svn://svn.valgrind.org/vex/trunk@2312 --- diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index cfad56a65d..515fe1bc11 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -254,6 +254,11 @@ static UInt ifieldOPClo9 ( UInt instr) { 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 @@ static Bool dis_dfp_fmt_convq(UInt theInstr) { 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 @@ DisResult disInstr_PPC_WRK ( 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 @@ DisResult disInstr_PPC_WRK ( 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 @@ DisResult disInstr_PPC_WRK ( 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,6 +14702,21 @@ DisResult disInstr_PPC_WRK ( 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 @@ -14332,9 +14800,30 @@ DisResult disInstr_PPC_WRK ( 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: diff --git a/VEX/priv/host_generic_regs.h b/VEX/priv/host_generic_regs.h index 0fde5ae822..e5c25b5263 100644 --- a/VEX/priv/host_generic_regs.h +++ b/VEX/priv/host_generic_regs.h @@ -188,7 +188,7 @@ extern void addHRegUse ( HRegUsage*, HRegMode, HReg ); 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 { diff --git a/VEX/priv/host_ppc_defs.c b/VEX/priv/host_ppc_defs.c index f8ff79c0a8..26a24ee4d9 100644 --- a/VEX/priv/host_ppc_defs.c +++ b/VEX/priv/host_ppc_defs.c @@ -644,7 +644,13 @@ HChar* showPPCFpOp ( PPCFpOp op ) { 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 @@ PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo, 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 @@ PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi, 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 @@ PPCInstr* PPCInstr_ProfInc ( void ) { return i; } - /* Valid combo | fromI | int32 | syned | flt64 | -------------------------------------------- @@ -1919,6 +2010,47 @@ void ppPPCInstr ( PPCInstr* i, Bool mode64 ) 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 @@ void ppPPCInstr ( PPCInstr* i, Bool mode64 ) 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 @@ void ppPPCInstr ( PPCInstr* i, Bool mode64 ) 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 @@ void ppPPCInstr ( PPCInstr* i, Bool mode64 ) 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 @@ void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 ) 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 @@ void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 ) 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 @@ void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 ) 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 @@ void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 ) 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 @@ static UChar* mkFormZ22 ( UChar* p, UInt opc1, UInt r1, UInt r2, 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 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc, 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 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc, * 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 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc, 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); @@ -4840,6 +5148,113 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc, 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 ); @@ -4888,6 +5303,76 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc, 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. */ diff --git a/VEX/priv/host_ppc_defs.h b/VEX/priv/host_ppc_defs.h index 1a1f90217b..871ec9f4e7 100644 --- a/VEX/priv/host_ppc_defs.h +++ b/VEX/priv/host_ppc_defs.h @@ -370,13 +370,15 @@ typedef /* 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 @@ typedef * 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 */ } @@ -863,6 +878,47 @@ typedef 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; @@ -875,6 +931,20 @@ typedef 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; @@ -951,7 +1021,7 @@ extern PPCInstr* PPCInstr_Dfp64Unary ( PPCFpOp op, HReg dst, HReg src ); extern PPCInstr* PPCInstr_Dfp64Binary ( PPCFpOp op, HReg dst, HReg srcL, HReg srcR ); extern PPCInstr* PPCInstr_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 @@ extern PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg src_hi, 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 ); diff --git a/VEX/priv/host_ppc_isel.c b/VEX/priv/host_ppc_isel.c index f573f5fa87..aac2a813fc 100644 --- a/VEX/priv/host_ppc_isel.c +++ b/VEX/priv/host_ppc_isel.c @@ -1497,9 +1497,13 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 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,7 +1511,22 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 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 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) 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 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) 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,47 +3670,62 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e) } 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) { @@ -3703,10 +3755,22 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e) 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 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e) 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 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e) 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 @@ static void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env, IRExpr* 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; } @@ -3849,10 +3954,38 @@ static void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env, IRExpr* e) *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 @@ static void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env, IRExpr* e) *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 ); diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c index d38acd73bb..ac2fbbf6a7 100644 --- a/VEX/priv/ir_defs.c +++ b/VEX/priv/ir_defs.c @@ -957,10 +957,24 @@ void ppIROp ( IROp op ) 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 @@ void typeOfPrimop ( IROp op, 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 @@ void typeOfPrimop ( IROp op, 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 ); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 91239adbd5..7182f33af1 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -991,14 +991,12 @@ typedef /* 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 @@ typedef * 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 @@ typedef /* 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 --- */