]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
POWER Processor decimal floating point instruction support: part 2
authorJulian Seward <jseward@acm.org>
Thu, 12 Apr 2012 17:19:48 +0000 (17:19 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 12 Apr 2012 17:19:48 +0000 (17:19 +0000)
(bug #297497) (Carl Love, carll@us.ibm.com) (VEX side)

This commit adds the second set of patches to add decimal floating
point (DFP) support for POWER to Valgrind. Bugzilla 295221 contains
the first set of patches for the adding the POWER support for the DFP
32, 64 and 128-bit sizes. The first set of patches also added support
for the 64 and 128-bit DFP arithmetic instructions and user test code
for the new DFP instructions. The second set of patches, being
submitted in this bugzilla include support for the DFP shift
instructions and format conversion instructions. Specifically, the
list of Power instructions is: dctdp, drsp, dctfix, dcffix, dctqpq,
dctfixq, drdpq, dcffixq, dscri, dscriq, dscli, dscliq.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2277

VEX/priv/guest_ppc_toIR.c
VEX/priv/host_ppc_defs.c
VEX/priv/host_ppc_defs.h
VEX/priv/host_ppc_isel.c
VEX/priv/ir_defs.c
VEX/pub/libvex_ir.h

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