Fixed up front and backend for 32bit mul,div,cmp,shift in mode64
Backend:
 - separated shifts from other alu ops
 - gave {shift, mul, div, cmp} ops a bool to indicate 32|64bit insn
 - fixed and implemented more mode64 cases

Also improved some IR by moving imm's to right arg of binop - backend assumes this.

All integer ppc32 insns now pass switchback tests in 64bit mode.
(ppc64-only insns not yet fully tested)




git-svn-id: svn://svn.valgrind.org/vex/trunk@1498 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host-ppc32/hdefs.c b/priv/host-ppc32/hdefs.c
index 82a2406..0ece9d5 100644
--- a/priv/host-ppc32/hdefs.c
+++ b/priv/host-ppc32/hdefs.c
@@ -573,23 +573,29 @@
    }
 }
 
-HChar* showPPC32AluOp ( PPC32AluOp op, Bool immR, Bool is32Bit ) {
+HChar* showPPC32AluOp ( PPC32AluOp op, Bool immR ) {
    switch (op) {
       case Palu_ADD: return immR ? "addi"  : "add";
       case Palu_SUB: return immR ? "subi"  : "sub";
       case Palu_AND: return immR ? "andi." : "and";
       case Palu_OR:  return immR ? "ori"   : "or";
       case Palu_XOR: return immR ? "xori"  : "xor";
-      case Palu_SHL: return is32Bit ? (immR ? "slwi"  : "slw") : 
-                                      (immR ? "sldi"  : "sld");
-      case Palu_SHR: return is32Bit ? (immR ? "srwi"  : "srw") :
-                                      (immR ? "srdi"  : "srd");
-      case Palu_SAR: return is32Bit ? (immR ? "srawi" : "sraw") :
-                                      (immR ? "sradi" : "srad");
       default: vpanic("showPPC32AluOp");
    }
 }
 
+HChar* showPPC32ShftOp ( PPC32ShftOp op, Bool immR, Bool sz32 ) {
+   switch (op) {
+      case Pshft_SHL: return sz32 ? (immR ? "slwi"  : "slw") : 
+                                    (immR ? "sldi"  : "sld");
+      case Pshft_SHR: return sz32 ? (immR ? "srwi"  : "srw") :
+                                    (immR ? "srdi"  : "srd");
+      case Pshft_SAR: return sz32 ? (immR ? "srawi" : "sraw") :
+                                    (immR ? "sradi" : "srad");
+      default: vpanic("showPPC32ShftOp");
+   }
+}
+
 HChar* showPPC32FpOp ( PPC32FpOp op ) {
    switch (op) {
       case Pfp_ADD:    return "fadd";
@@ -719,6 +725,17 @@
    i->Pin.Alu.srcR = srcR;
    return i;
 }
+PPC32Instr* PPC32Instr_Shft ( PPC32ShftOp op, Bool sz32, 
+                              HReg dst, HReg srcL, PPC32RH* srcR ) {
+   PPC32Instr* i    = LibVEX_Alloc(sizeof(PPC32Instr));
+   i->tag           = Pin_Shft;
+   i->Pin.Shft.op   = op;
+   i->Pin.Shft.sz32 = sz32;
+   i->Pin.Shft.dst  = dst;
+   i->Pin.Shft.srcL = srcL;
+   i->Pin.Shft.srcR = srcR;
+   return i;
+}
 PPC32Instr* PPC32Instr_AddSubC32 ( Bool isAdd, Bool setC,
                                    HReg dst, HReg srcL, HReg srcR ) {
    PPC32Instr* i          = LibVEX_Alloc(sizeof(PPC32Instr));
@@ -730,11 +747,12 @@
    i->Pin.AddSubC32.srcR  = srcR;
    return i;
 }
-PPC32Instr* PPC32Instr_Cmp ( Bool syned, UInt crfD, 
-                             HReg srcL, PPC32RH* srcR ) {
+PPC32Instr* PPC32Instr_Cmp ( Bool syned, Bool sz32, 
+                             UInt crfD, HReg srcL, PPC32RH* srcR ) {
    PPC32Instr* i    = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag           = Pin_Cmp;
    i->Pin.Cmp.syned = syned;
+   i->Pin.Cmp.sz32  = sz32;
    i->Pin.Cmp.crfD  = crfD;
    i->Pin.Cmp.srcL  = srcL;
    i->Pin.Cmp.srcR  = srcR;
@@ -748,12 +766,13 @@
    i->Pin.Unary32.src = src;
    return i;
 }
-PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool hi, 
+PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool hi, Bool sz32, 
                               HReg dst, HReg srcL, HReg srcR ) {
    PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag            = Pin_MulL;
    i->Pin.MulL.syned = syned;
    i->Pin.MulL.hi    = hi;
+   i->Pin.MulL.sz32  = sz32;
    i->Pin.MulL.dst   = dst;
    i->Pin.MulL.srcL  = srcL;
    i->Pin.MulL.srcR  = srcR;
@@ -762,10 +781,12 @@
    if (!hi) vassert(!syned);
    return i;
 }
-PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) {
+PPC32Instr* PPC32Instr_Div ( Bool syned, Bool sz32,
+                             HReg dst, HReg srcL, HReg srcR ) {
    PPC32Instr* i      = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag             = Pin_Div;
    i->Pin.Div.syned   = syned;
+   i->Pin.Div.sz32    = sz32;
    i->Pin.Div.dst     = dst;
    i->Pin.Div.srcL    = srcL;
    i->Pin.Div.srcR    = srcR;
@@ -1137,17 +1158,39 @@
          ppHRegPPC32(i->Pin.Alu.dst);
          vex_printf(",");
          ppHRegPPC32(r_srcL);
-      } else {
-         /* generic */
-         vex_printf("%s ", showPPC32AluOp(i->Pin.Alu.op,
-                                toBool(rh_srcR->tag == Prh_Imm),
-                                toBool(hregClass(r_srcL) == HRcInt32)));
+         return;
+      }
+      /* special-case "li" */
+      if (i->Pin.Alu.op == Palu_ADD &&   // addi Rd,0,imm == li Rd,imm
+          rh_srcR->tag == Prh_Imm &&
+          hregNumber(r_srcL) == 0) {
+         vex_printf("li ");
          ppHRegPPC32(i->Pin.Alu.dst);
          vex_printf(",");
-         ppHRegPPC32(r_srcL);
-         vex_printf(",");
          ppPPC32RH(rh_srcR);
+         return;
       }
+      /* generic */
+      vex_printf("%s ", showPPC32AluOp(i->Pin.Alu.op,
+                                       toBool(rh_srcR->tag == Prh_Imm)));
+      ppHRegPPC32(i->Pin.Alu.dst);
+      vex_printf(",");
+      ppHRegPPC32(r_srcL);
+      vex_printf(",");
+      ppPPC32RH(rh_srcR);
+      return;
+   }
+   case Pin_Shft: {
+      HReg     r_srcL  = i->Pin.Shft.srcL;
+      PPC32RH* rh_srcR = i->Pin.Shft.srcR;
+      vex_printf("%s ", showPPC32ShftOp(i->Pin.Shft.op,
+                                        toBool(rh_srcR->tag == Prh_Imm),
+                                        i->Pin.Shft.sz32));
+      ppHRegPPC32(i->Pin.Shft.dst);
+      vex_printf(",");
+      ppHRegPPC32(r_srcL);
+      vex_printf(",");
+      ppPPC32RH(rh_srcR);
       return;
    }
    case Pin_AddSubC32:
@@ -1161,8 +1204,9 @@
       ppHRegPPC32(i->Pin.AddSubC32.srcR);
       return;
    case Pin_Cmp:
-      vex_printf("%s%s %%cr%u,",
+      vex_printf("%s%c%s %%cr%u,",
                  i->Pin.Cmp.syned ? "cmp" : "cmpl",
+                 i->Pin.Cmp.sz32 ? 'w' : 'd',
                  i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
                  i->Pin.Cmp.crfD);
       ppHRegPPC32(i->Pin.Cmp.srcL);
@@ -1176,8 +1220,9 @@
       ppHRegPPC32(i->Pin.Unary32.src);
       return;
    case Pin_MulL:
-      vex_printf("mul%s%s ",
-                 i->Pin.MulL.hi ? "hw" : "lw",
+      vex_printf("mul%c%c%s ",
+                 i->Pin.MulL.hi ? 'h' : 'l',
+                 i->Pin.MulL.sz32 ? 'w' : 'd',
                  i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
       ppHRegPPC32(i->Pin.MulL.dst);
       vex_printf(",");
@@ -1186,7 +1231,8 @@
       ppHRegPPC32(i->Pin.MulL.srcR);
       return;
    case Pin_Div:
-      vex_printf("divw%s ",
+      vex_printf("div%c%s ",
+                 i->Pin.Div.sz32 ? 'w' : 'd',
                  i->Pin.Div.syned ? "" : "u");
       ppHRegPPC32(i->Pin.Div.dst);
       vex_printf(",");
@@ -1555,6 +1601,11 @@
       addRegUsage_PPC32RH(u, i->Pin.Alu.srcR);
       addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
       return;
+   case Pin_Shft:
+      addHRegUse(u, HRmRead,  i->Pin.Shft.srcL);
+      addRegUsage_PPC32RH(u,  i->Pin.Shft.srcR);
+      addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
+      return;
    case Pin_AddSubC32:
       addHRegUse(u, HRmWrite, i->Pin.AddSubC32.dst);
       addHRegUse(u, HRmRead, i->Pin.AddSubC32.srcL);
@@ -1800,6 +1851,11 @@
       mapReg(m, &i->Pin.Alu.srcL);
       mapRegs_PPC32RH(m, i->Pin.Alu.srcR);
       return;
+   case Pin_Shft:
+      mapReg(m, &i->Pin.Shft.dst);
+      mapReg(m, &i->Pin.Shft.srcL);
+      mapRegs_PPC32RH(m, i->Pin.Shft.srcR);
+      return;
    case Pin_AddSubC32:
       mapReg(m, &i->Pin.AddSubC32.dst);
       mapReg(m, &i->Pin.AddSubC32.srcL);
@@ -2429,10 +2485,8 @@
       UInt     r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
       UInt     r_srcR = immR ? (-1)/*bogus*/ :
                                iregNo(srcR->Prh.Reg.reg, mode64);
-      Bool  is32BitOp = toBool(hregClass(i->Pin.Alu.srcL) == HRcInt32);
 
       switch (i->Pin.Alu.op) {
-
       case Palu_ADD:
          if (immR) {
             /* addi (PPC32 p350) */
@@ -2490,9 +2544,26 @@
          }
          break;
 
-      case Palu_SHL:
-         if (is32BitOp) {
-            vassert(!mode64);
+      default:
+         goto bad;
+      }
+      goto done;
+   }
+
+   case Pin_Shft: {
+      PPC32RH* srcR   = i->Pin.Shft.srcR;
+      Bool     sz32   = i->Pin.Shft.sz32;
+      Bool     immR   = toBool(srcR->tag == Prh_Imm);
+      UInt     r_dst  = iregNo(i->Pin.Shft.dst, mode64);
+      UInt     r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
+      UInt     r_srcR = immR ? (-1)/*bogus*/ :
+                               iregNo(srcR->Prh.Reg.reg, mode64);
+      if (!mode64)
+         vassert(sz32);
+
+      switch (i->Pin.Shft.op) {
+      case Pshft_SHL:
+         if (sz32) {
             if (immR) {
                /* rd = rs << n, 1 <= n <= 31
                   is
@@ -2507,7 +2578,6 @@
                p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
             }
          } else {
-            vassert(mode64);
             if (immR) {
                /* rd = rs << n, 1 <= n <= 63
                   is
@@ -2524,10 +2594,9 @@
          }
          break;
 
-      case Palu_SHR:
-         if (is32BitOp) {
-            vassert(!mode64);
-            if (immR) {
+      case Pshft_SHR:
+         if (sz32) {
+             if (immR) {
                /* rd = rs >>u n, 1 <= n <= 31
                   is
                   rlwinm rd,rs,32-n,n,31  (PPC32 p501)
@@ -2541,7 +2610,6 @@
                p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
             }
          } else {
-            vassert(mode64);
             if (immR) {
                /* rd = rs >>u n, 1 <= n <= 63
                   is
@@ -2558,9 +2626,8 @@
          }
          break;
 
-      case Palu_SAR:
-         if (is32BitOp) {
-            vassert(!mode64);
+      case Pshft_SAR:
+         if (sz32) {
             if (immR) {
                /* srawi (PPC32 p507) */
                UInt n = srcR->Prh.Imm.imm16;
@@ -2572,7 +2639,6 @@
                p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
             }
          } else {
-            vassert(mode64);
             if (immR) {
                /* sradi (PPC64 p571) */
                UInt n = srcR->Prh.Imm.imm16;
@@ -2616,29 +2682,34 @@
 
    case Pin_Cmp: {
       Bool syned  = i->Pin.Cmp.syned;
+      Bool sz32   = i->Pin.Cmp.sz32;
       UInt fld1   = i->Pin.Cmp.crfD << 2;
       UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
       UInt r_srcR, imm_srcR;
       PPC32RH* srcR = i->Pin.Cmp.srcR;
 
+      if (!mode64)        // cmp double word invalid for mode32
+         vassert(sz32);      
+      else if (!sz32)     // mode64 && cmp64: set L=1
+         fld1 |= 1;
+ 
       switch (srcR->tag) {
       case Prh_Imm:
-         /* cmpi  (signed)   (PPC32 p368)  or 
-            cmpli (unsigned) (PPC32 p370) */
+         vassert(syned == srcR->Prh.Imm.syned);
          imm_srcR = srcR->Prh.Imm.imm16;
-         if (syned) {
-            vassert(srcR->Prh.Imm.syned);
+         if (syned) {  // cmpw/di  (signed)   (PPC32 p368)
             vassert(imm_srcR != 0x8000);
-         } else {
-            vassert(!srcR->Prh.Imm.syned);
+            p = mkFormD(p, 11, fld1, r_srcL, imm_srcR);
+         } else {      // cmplw/di (unsigned) (PPC32 p370)
+            p = mkFormD(p, 10, fld1, r_srcL, imm_srcR);
          }
-         p = mkFormD(p, syned ? 11 : 10, fld1, r_srcL, imm_srcR);
          break;
       case Prh_Reg:
-         /* cmpi  (signed)   (PPC32 p367)  or 
-            cmpli (unsigned) (PPC32 p379) */
          r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
-         p = mkFormX(p, 31, fld1, r_srcL, r_srcR, syned ? 0 : 32, 0);
+         if (syned)  // cmpwi  (signed)   (PPC32 p367)
+            p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0);
+         else        // cmplwi (unsigned) (PPC32 p379)
+            p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0);
          break;
       default: 
          goto bad;
@@ -2667,30 +2738,33 @@
 
    case Pin_MulL: {
       Bool syned  = i->Pin.MulL.syned;
+      Bool sz32   = i->Pin.MulL.sz32;
       UInt r_dst  = iregNo(i->Pin.MulL.dst, mode64);
       UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
       UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
-      Bool is32BitOp = toBool(hregClass(i->Pin.MulL.dst) == HRcInt32);
+
+      if (!mode64)
+         vassert(sz32);
 
       if (i->Pin.MulL.hi) {
          // mul hi words, must consider sign
-         if (syned) {
-            if (is32BitOp)  // mulhw r_dst,r_srcL,r_srcR
+         if (sz32) {
+            if (syned)  // mulhw r_dst,r_srcL,r_srcR
                p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
-            else            // mulhd r_dst,r_srcL,r_srcR
-               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0);
-         } else {
-            if (is32BitOp)  // mulhwu r_dst,r_srcL,r_srcR
+            else        // mulhwu r_dst,r_srcL,r_srcR
                p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
-            else            // mulhdu r_dst,r_srcL,r_srcR
+         } else {
+            if (syned)  // mulhd r_dst,r_srcL,r_srcR
+               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0);
+            else        // mulhdu r_dst,r_srcL,r_srcR
                p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0);
          }
       } else {
          // mul low word, sign is irrelevant
          vassert(!i->Pin.MulL.syned);
-         if (is32BitOp)     // mullw r_dst,r_srcL,r_srcR
+         if (sz32)      // mullw r_dst,r_srcL,r_srcR
             p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
-         else               // mulld r_dst,r_srcL,r_srcR
+         else           // mulld r_dst,r_srcL,r_srcR
             p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0);
       }
       goto done;
@@ -2698,20 +2772,23 @@
 
    case Pin_Div: {
       Bool syned  = i->Pin.Div.syned;
+      Bool sz32   = i->Pin.Div.sz32;
       UInt r_dst  = iregNo(i->Pin.Div.dst, mode64);
       UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
       UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
-      Bool is32BitOp = toBool(hregClass(i->Pin.Div.dst) == HRcInt32);
 
-      if (syned == True) {
-         if (is32BitOp)  // divw r_dst,r_srcL,r_srcR
+      if (!mode64)
+         vassert(sz32);
+
+      if (sz32) {
+         if (syned)  // divw r_dst,r_srcL,r_srcR
             p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
-         else
-            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0);
-      } else {
-         if (is32BitOp)  // divwu r_dst,r_srcL,r_srcR
+         else        // divwu r_dst,r_srcL,r_srcR
             p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
-         else
+      } else {
+         if (syned)  // divd r_dst,r_srcL,r_srcR
+            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0);
+         else        // divdu r_dst,r_srcL,r_srcR
             p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0);
       }
       goto done;