]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
hdefs
authorCerion Armour-Brown <cerion@valgrind.org>
Wed, 16 Feb 2005 14:14:49 +0000 (14:14 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Wed, 16 Feb 2005 14:14:49 +0000 (14:14 +0000)
-----
Sorted out Mul
 - removed from Alu32
 - replaced with proper Pin_MulL

More instr emitting
 - cmp32, unary32, mulL, cmov, set32, mfence

isel
----
Added a couple of handy funcs:
 - mk_FitRI16, mk_RItoR
Reworked div, mul, mfence

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

VEX/priv/host-ppc32/hdefs.c
VEX/priv/host-ppc32/hdefs.h
VEX/priv/host-ppc32/isel.c

index ae44e9be6ee2ea532d281551de97866b9f765d8a..093bdc4f8af0a33749a510bb8df7d8f58bd4d413 100644 (file)
@@ -394,7 +394,6 @@ HChar* showPPC32AluOp ( PPC32AluOp op ) {
    case Palu_AND:  return "and";
    case Palu_OR:   return "or";
    case Palu_XOR:  return "xor";
-   case Palu_MUL:  return "mull";
    default: vpanic("showPPC32AluOp");
    }
 }
@@ -492,6 +491,14 @@ PPC32Instr* PPC32Instr_Unary32  ( PPC32UnaryOp op, HReg dst, HReg src ) {
 }
 PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
                               HReg src1, PPC32RI* src2 ) {
+   if (word == 1) { // high
+      vassert(src2->tag == Pri_Reg);
+   } else {         // low
+      if (src2->tag == Pri_Imm) {
+         vassert(syned == True);
+         vassert(src2->Pri.Imm.imm32 < 0x10000);
+      }
+   }
    PPC32Instr* i     = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag            = Pin_MulL;
    i->Pin.MulL.syned = syned;
@@ -587,13 +594,10 @@ PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
 //..    i->Xin.Bsfr32.dst    = dst;
 //..    return i;
 //.. }
-PPC32Instr* PPC32Instr_MFence ( VexSubArch subarch )
+PPC32Instr* PPC32Instr_MFence ( void )
 {
    PPC32Instr* i         = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag                = Pin_MFence;
-   i->Pin.MFence.subarch = subarch;
-   vassert(subarch == VexSubArchPPC32_AV
-           || subarch == VexSubArchPPC32_noAV);
    return i;
 }
 
@@ -769,7 +773,7 @@ void ppPPC32Instr ( PPC32Instr* i )
 //..          ppX86RMI(i->Xin.Push.src);
 //..          return;
    case Pin_Call:
-      vex_printf("call: la r12, 0x%x ; mtctr r12 ; bcctrl[%d] %s,reg",
+      vex_printf("call: la r12, 0x%x ; mtctr r12 ; bcctrl[%d] %s",
                  i->Pin.Call.target,
                  i->Pin.Call.regparms,
                  showPPC32CondCode(i->Pin.Call.cond));
@@ -841,8 +845,7 @@ void ppPPC32Instr ( PPC32Instr* i )
 //..          ppHRegX86(i->Xin.Bsfr32.dst);
 //..          return;
    case Pin_MFence:
-      vex_printf("mfence(%s)",
-                 LibVEX_ppVexSubArch(i->Pin.MFence.subarch));
+      vex_printf("mfence (=sync)");
       return;
 //..       case Xin_FpUnary:
 //..          vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
@@ -1805,7 +1808,6 @@ static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
    return emit32(p, theInstr);
 }
 
-#if 0
 // rotates
 static UChar* mkFormM ( UChar* p, UInt op1, UInt r1, UInt r2,
                         UInt f3, UInt MB, UInt ME, UInt Rc )
@@ -1821,7 +1823,6 @@ static UChar* mkFormM ( UChar* p, UInt op1, UInt r1, UInt r2,
                     (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
    return emit32(p, theInstr);
 }
-#endif
 
 static UChar* doAMode_IR ( UChar* p, UInt op1, HReg hrSD, PPC32AMode* am )
 {
@@ -1877,33 +1878,6 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
       UInt r_dst  = iregNo(i->Pin.Alu32.dst);
       UInt r_src1 = iregNo(i->Pin.Alu32.src1);
 
-#if 0
-      /* MUL */
-      if (i->Pin.Alu32.op == Palu_MUL) {
-         switch (i->Pin.Alu32.src->tag) {
-            case Pri_Reg:
-               *p++ = 0x0F;
-               *p++ = 0xAF;
-               p = doAMode_R(p, i->Pin.Alu32.dst,
-                                i->Pin.Alu32.src->Pri.Reg.reg);
-               goto done;
-            case Pri_Imm:
-               if (fits8bits(i->Pin.Alu32.src->Pri.Imm.imm32)) {
-                  *p++ = 0x6B;
-                  p = doAMode_R(p, i->Pin.Alu32.dst, i->Pin.Alu32.dst);
-                  *p++ = 0xFF & i->Pin.Alu32.src->Pri.Imm.imm32;
-               } else {
-                  *p++ = 0x69;
-                  p = doAMode_R(p, i->Pin.Alu32.dst, i->Pin.Alu32.dst);
-                  p = emit32(p, i->Pin.Alu32.src->Pri.Imm.imm32);
-               }
-               goto done;
-            default:
-               goto bad;
-         }
-      }
-#endif
-
       /* ADD/SUB/ADC/SBB/AND/OR/XOR */
       if (i->Pin.Alu32.src2->tag == Pri_Reg) {
          op1 = 31;
@@ -2005,48 +1979,90 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 //..       }
 //..       break;
 
-//..    case Pin_Cmp32:
-//..       goto done;
+   case Pin_Cmp32: {
+      UInt opc1, opc2=0;
+      UInt op = i->Pin.Cmp32.op;
+      UInt fld1 = i->Pin.Cmp32.crfD << 2;
+      UInt r1 = iregNo(i->Pin.Cmp32.src1);
+      UInt r2, imm;
 
-//..    case Xin_Unary32:
-//..       if (i->Xin.Unary32.op == Xun_NOT) {
-//..          *p++ = 0xF7;
-//..          if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
-//..             p = doAMode_R(p, fake(2), i->Xin.Unary32.dst->Xrm.Reg.reg);
-//..             goto done;
-//..          } else {
-//..             goto bad;
-//..          }
-//..       }
-//..       if (i->Xin.Unary32.op == Xun_NEG) {
-//..          *p++ = 0xF7;
-//..          if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
-//..             p = doAMode_R(p, fake(3), i->Xin.Unary32.dst->Xrm.Reg.reg);
-//..             goto done;
-//..          } else {
-//..             goto bad;
-//..          }
-//..       }
-//..       break;
+      switch (i->Pin.Cmp32.src2->tag) {
+      case Pri_Imm:
+         opc1 = (op == Pcmp_U) ? 10 : 11;
+         imm = i->Pin.Cmp32.src2->Pri.Imm.imm32;
+         p = mkFormD(p, opc1, fld1, r1, imm);
+         break;
+      case Pri_Reg:
+         opc1 = 31;
+         opc2 = (op == Pcmp_U) ? 32 : 0;
+         r2 = iregNo(i->Pin.Cmp32.src2->Pri.Reg.reg);
+         p = mkFormX(p, opc1, fld1, r1, r2, opc2, 0);
+         break;
+      default: goto bad;
+      }        
+      goto done;
+   }
 
-//..    case Xin_MulL:
-//..       subopc = i->Xin.MulL.syned ? 5 : 4;
-//..       if (i->Xin.MulL.ssz == Xss_32) {
-//..          *p++ = 0xF7;
-//..          switch (i->Xin.MulL.src->tag)  {
-//..             case Xrm_Mem:
-//..                p = doAMode_M(p, fake(subopc),
-//..                                 i->Xin.MulL.src->Xrm.Mem.am);
-//..                goto done;
-//..             case Xrm_Reg:
-//..                p = doAMode_R(p, fake(subopc), 
-//..                                 i->Xin.MulL.src->Xrm.Reg.reg);
-//..                goto done;
-//..             default:
-//..                goto bad;
-//..          }
-//..       }
-//..       break;
+   case Pin_Unary32: {
+      UInt r_dst = iregNo(i->Pin.Unary32.dst);
+      UInt r_src = iregNo(i->Pin.Unary32.src);
+
+      switch (i->Pin.Unary32.op) {
+      case Pun_NOT:  // nor r_dst,r_src,r_src
+         p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
+         break;
+      case Pun_NEG:  // neg r_dst,r_src
+         p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
+         break;
+      case Pun_CLZ:  // cntlzw r_dst, r_src
+         p = mkFormX(p, 31, r_dst, r_src, 0, 26, 0);
+         break;
+      default: goto bad;
+      }
+      goto done;
+   }
+
+   case Pin_MulL: {
+      Bool syned  = i->Pin.MulL.syned;
+      UInt r_dst  = iregNo(i->Pin.MulL.dst);
+      UInt r_src1 = iregNo(i->Pin.MulL.src1);
+      UInt r_src2, imm;
+
+      switch (i->Pin.MulL.word) {
+      case 0:       // multiply low word
+         switch (i->Pin.MulL.src2->tag) {
+         case Pri_Reg:
+            // mullw r_dst,r_src1,r_src2
+            // sign makes no difference.
+            r_src2 = iregNo(i->Pin.MulL.src2->Pri.Reg.reg);
+            p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 235, 0);
+            break;
+         case Pri_Imm:
+            // mulli r_dst,r_src,imm
+            vassert(syned == True);  // always signed
+            imm = i->Pin.MulL.src2->Pri.Imm.imm32;
+            p = mkFormD(p, 07, r_dst, r_src1, imm);
+            break;
+         default:
+            goto bad;
+         }
+         break;
+      case 1:       // multiply high word
+         vassert(i->Pin.MulL.src2->tag == Pri_Reg);
+         r_src2 = iregNo(i->Pin.MulL.src2->Pri.Reg.reg);
+         if (syned == True) {
+            // mulhw r_dst,r_src1,r_src2
+            p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 75, 0);
+         } else {
+            // mulhwu r_dst,r_src1,r_src2
+            p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 11, 0);
+         }
+         break;
+      default:
+         goto bad;
+      }
+      goto done;
+   }
 
 //..    case Xin_Div:
 //..       subopc = i->Xin.Div.syned ? 7 : 6;
@@ -2177,11 +2193,16 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 // CAB: Which reg?  On amd64,x86, does 'ret' use rax,eax somehow?
       r_dst = 4;
       if (i->Pin.Goto.dst->tag == Pri_Imm) {
-         /* addi r_dst,0,(imm & 0xFFFF)
-            addis r_dst,r_dst,((imm >> 16) & 0xFFFF) */
          imm = i->Pin.Goto.dst->Pri.Imm.imm32;
-         p = mkFormD(p, 14, r_dst, 0, (imm & 0xFFFF));
-         p = mkFormD(p, 15, r_dst, r_dst, ((imm>>16) & 0xFFFF));
+         if (imm < 0x10000) {
+            // addi r_dst,0,(imm & 0xFFFF)
+            p = mkFormD(p, 14, r_dst, 0, imm);
+         } else {
+            // addi r_dst,0,(imm & 0xFFFF)
+            // addis r_dst,r_dst,((imm >> 16) & 0xFFFF)
+            p = mkFormD(p, 14, r_dst, 0, (imm & 0xFFFF));
+            p = mkFormD(p, 15, r_dst, r_dst, ((imm>>16) & 0xFFFF));
+         }
       } else {
          vassert(i->Pin.Goto.dst->tag == Pri_Reg);
          if (i->Pin.Goto.dst->Pri.Reg.reg != hregPPC32_GPR4()) {
@@ -2198,52 +2219,41 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
       goto done;
    }
 
-//..    case Xin_CMov32:
-//..       vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
-//.. #if 0
-//..       /* This generates cmov, which is illegal on P54/P55. */
-//..       *p++ = 0x0F;
-//..       *p++ = 0x40 + i->Xin.CMov32.cond;
-//..       if (i->Xin.CMov32.src->tag == Xrm_Reg) {
-//..          p = doAMode_R(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Reg.reg);
-//..          goto done;
-//..       }
-//..       if (i->Xin.CMov32.src->tag == Xrm_Mem) {
-//..          p = doAMode_M(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Mem.am);
-//..          goto done;
-//..       }
-//.. #else
-//..       /* P5 friendly version: conditional jump over an unconditional
-//..          move. */
-//..       /* jmp fwds if !condition */
-//..       *p++ = 0x70 + (i->Xin.CMov32.cond ^ 1);
-//..       *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
-//..       ptmp = p;
-//.. 
-//..       switch (i->Xin.CMov32.src->tag) {
-//..          case Xrm_Reg:
-//..             /* Big sigh.  This is movl E -> G ... */
-//..             *p++ = 0x89;
-//..             p = doAMode_R(p, i->Xin.CMov32.src->Xrm.Reg.reg,
-//..                              i->Xin.CMov32.dst);
-//..                              
-//..             break;
-//..          case Xrm_Mem:
-//..             /* ... whereas this is movl G -> E.  That's why the args
-//..                to doAMode_R appear to be the wrong way round in the
-//..                Xrm_Reg case. */
-//..             *p++ = 0x8B;
-//..             p = doAMode_M(p, i->Xin.CMov32.dst, 
-//..                              i->Xin.CMov32.src->Xrm.Mem.am);
-//..             break;
-//..          default:
-//..             goto bad;
-//..       }
-//..       /* Fill in the jump offset. */
-//..       *(ptmp-1) = p - ptmp;
-//..       goto done;
-//.. #endif
-//..       break;
+   case Pin_CMov32: {
+      vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
+      UInt r_dst = iregNo(i->Pin.CMov32.dst);
+      PPC32CondCode cond = i->Pin.CMov32.cond;
+      UInt imm, r_src;
+
+      // branch (if cond false) over next instr
+      // bc false,cond,8
+      p = mkFormB(p, invertCondTest(cond.test), cond.flag, 8, 0, 0);
+
+      // cond true: move src => dst
+      switch (i->Pin.CMov32.src->tag) {
+      case Pri_Imm:
+         imm = i->Pin.CMov32.src->Pri.Imm.imm32;
+         if (imm < 0x10000) {
+            // addi r_dst,0,imm
+            p = mkFormD(p, 14, r_dst, 0, imm);
+         } else {
+            // addi r_dst,0,(imm & 0xFFFF)
+            // addis r_dst,r_dst,((imm >> 16) & 0xFFFF)
+            p = mkFormD(p, 14, r_dst, 0, (imm & 0xFFFF));
+            p = mkFormD(p, 15, r_dst, r_dst, ((imm>>16) & 0xFFFF));
+         }
+         break;
+      case Pri_Reg:
+         r_src = iregNo(i->Pin.CMov32.src->Pri.Reg.reg);
+         if (r_src != r_dst) {
+            /* add r_dst, 0, r_src */
+            p = mkFormXO(p, 31, r_dst, 0, r_src, 0, 266, 0);
+         }
+         break;
+      default: goto bad;
+      }
+      goto done;
+   }
 
    case Pin_LoadEX: {
       UInt op1, op2, sz = i->Pin.LoadEX.sz;
@@ -2274,24 +2284,33 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 
    case Pin_Set32: {
       /* Make the destination register be 1 or 0, depending on whether
-         the relevant condition holds. Yay - mfcr doesn't change CR. */
- /*
-      HReg rD = i->Xin.Set32.dst;
-      if (i->Xin.Set32.cond.test == Pct_ALWAYS) {
-         // just load 1 to i->Xin.Set32.dst
-         // addi rD,r0,1
+         the relevant condition holds. Yay! - mfcr doesn't change CR. */
+      UInt r_dst = iregNo(i->Pin.Set32.dst);
+      PPC32CondCode cond = i->Pin.Set32.cond;
+      UInt shft;
+      UInt r_tmp;
+
+      if (cond.test == Pct_ALWAYS) {
+         // just load 1 to dst => li dst,1
+         p = mkFormD(p, 14, r_dst, 0, 1);
       } else {
-         UInt shft = 32 - cond.flag;
-// CAB: how choose r1 so don't kill anything else?
-         // mfcr r1                      // r1 = CR
-         // rlwinm rD,r1,shft,31,31      // r2 = flag (rotate left and mask)
-         if (cond.test == Pct_False) {
-            // xori rD,rD,1              // flip bit
+         shft = 32 - cond.flag;
+         r_tmp = 1;
+// CAB: how choose r_tmp so don't kill anything else?
+
+         // r_tmp = CR  => mfcr r_tmp
+         p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
+
+         // r_dst = flag (rotate left and mask)
+         //  => rlwinm r_dst,r_tmp,shft,31,31
+         p = mkFormM(p, 21, r_dst, r_tmp, shft, 31, 31, 0);
+
+         if (cond.test == Pct_FALSE) {
+            // flip bit  => xori rD,rD,1
+            p = mkFormD(p, 26, r_dst, r_dst, 1);
          }
       }
       goto done;
-*/
-      goto bad;
    }
 
 //..    case Xin_Bsfr32:
@@ -2304,31 +2323,15 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 //..       p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
 //..       goto done;
 
-//..    case Xin_MFence:
-//..       /* see comment in hdefs.h re this insn */
-//..       if (0) vex_printf("EMIT FENCE\n");
-//..       switch (i->Xin.MFence.subarch) {
-//..          case VexSubArchX86_sse0:
-//..             vassert(0); /* awaiting test case */
-//..             /* lock addl $0,0(%esp) */
-//..             *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44; 
-//..             *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
-//..             goto done;
-//..          case VexSubArchX86_sse1:
-//..             /* sfence */
-//..             *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF8;
-//..             /* lock addl $0,0(%esp) */
-//..             *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44; 
-//..             *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
-//..             goto done;
-//..          case VexSubArchX86_sse2:
-//..             /* mfence */
-//..             *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF0;
-//..             goto done;
-//..          default: 
-//..             vpanic("emit_X86Instr:mfence:subarch");
-//..       }
-//..       break;
+   case Pin_MFence: {
+// CAB: choose...
+#if 1  // sync (Synchronise, p616)
+      p = mkFormX(p, 31, 0, 0, 0, 598, 0);
+#else  // isync (instruction synchronise, p467)
+      p = mkFormXL(p, 19, 0, 0, 0, 150, 0);
+#endif
+      goto done;
+   }
 
    case Pin_Store: {
       UInt op1, op2, sz = i->Pin.Store.sz;
index 8708d32433e1a599406f315d8ed7a046aea7dfa6..49e8ef7a05158e93909d888dd1b7a948865a0e69 100644 (file)
@@ -293,8 +293,7 @@ typedef
       Palu_INVALID,
       Palu_ADD, Palu_SUB,
 //      Palu_ADC, Palu_SBB,
-      Palu_AND, Palu_OR, Palu_XOR,
-      Palu_MUL
+      Palu_AND, Palu_OR, Palu_XOR
    }
    PPC32AluOp;
 
@@ -411,7 +410,7 @@ typedef
          /* DX:AX = AX *s/u r/m16,  or EDX:EAX = EAX *s/u r/m32 */
          struct {
             Bool     syned;
-            Bool     word;   /* low=0, hi=1 */
+            Bool     word;   /* low=0, high=1 */
             HReg     dst;
             HReg     src1;
             PPC32RI* src2;
@@ -481,15 +480,10 @@ typedef
 //..             HReg src;
 //..             HReg dst;
 //..          } Bsfr32;
-         /* Mem fence (not just sse2, but sse0 and 1 too).  In short,
-            an insn which flushes all preceding loads and stores as
-            much as possible before continuing.  On SSE2 we emit a
-            real "mfence", on SSE1 "sfence ; lock addl $0,0(%esp)" and
-            on SSE0 "lock addl $0,0(%esp)".  This insn therefore
-            carries the subarch so the assembler knows what to
-            emit. */
+         /* Mem fence.  In short, an insn which flushes all preceding
+            loads and stores as much as possible before continuing.
+            On PPC32 we emit a "sync". */
          struct {
-            VexSubArch subarch;
          } MFence;
 
 //..          /* X86 Floating point (fake 3-operand, "flat reg file" insns) */
@@ -573,7 +567,7 @@ extern PPC32Instr* PPC32Instr_LoadEX    ( UChar sz, Bool syned,
 extern PPC32Instr* PPC32Instr_Store     ( UChar sz, PPC32AMode* dst, HReg src );
 extern PPC32Instr* PPC32Instr_Set32     ( PPC32CondCode cond, HReg dst );
 //.. extern X86Instr* X86Instr_Bsfr32    ( Bool isFwds, HReg src, HReg dst );
-extern PPC32Instr* PPC32Instr_MFence    ( VexSubArch );
+extern PPC32Instr* PPC32Instr_MFence    ( void );
 //.. 
 //.. extern X86Instr* X86Instr_FpUnary   ( X86FpOp op, HReg src, HReg dst );
 //.. extern X86Instr* X86Instr_FpBinary  ( X86FpOp op, HReg srcL, HReg srcR, HReg dst );
index 9a9b908a32d4210a0090265ae44020c532ac3d13..04d5b2f949f5c8468a86be94e60bd16b6738a4ff 100644 (file)
@@ -128,6 +128,7 @@ static IRExpr* bind ( Int binder )
 
 
 
+
 /*---------------------------------------------------------*/
 /*--- ISelEnv                                           ---*/
 /*---------------------------------------------------------*/
@@ -338,6 +339,31 @@ static PPC32Instr* mk_iMOVds_RRI ( ISelEnv* env, HReg dst, PPC32RI* src )
    }
 }
 
+/* If imm > 0xffff, mov to reg first */
+static PPC32RI* mk_FitRI16 ( ISelEnv* env, PPC32RI* ri )
+{
+   HReg tmp = newVRegI(env);
+
+   if (ri->tag == Pri_Imm && ri->Pri.Imm.imm32 > 0xFFFF) {
+      addInstr(env, mk_iMOVds_RRI(env, tmp, ri));
+      return PPC32RI_Reg(tmp);
+   }
+   return ri;
+}
+
+/* Flatten RI to an R */
+static HReg mk_RItoR ( ISelEnv* env, PPC32RI* ri )
+{
+   HReg tmp = newVRegI(env);
+
+   if (ri->tag == Pri_Imm) {
+      addInstr(env, mk_iMOVds_RRI(env, tmp, ri));
+      return tmp;
+   } else {
+      return ri->Pri.Reg.reg;
+   }
+}
+
 //.. /* Make a vector reg-reg move. */
 //.. 
 //.. static X86Instr* mk_vMOVsd_RR ( HReg src, HReg dst )
@@ -816,8 +842,6 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          aluOp = Palu_OR; break;
       case Iop_Xor8:  case Iop_Xor16: case Iop_Xor32: 
          aluOp = Palu_XOR; break;
-      case Iop_Mul16: case Iop_Mul32: 
-         aluOp = Palu_MUL; break;
       default:
          aluOp = Palu_INVALID; break;
       }
@@ -825,16 +849,9 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          values are on the second operand. */
       if (aluOp != Palu_INVALID) {
          HReg dst    = newVRegI(env);
-         HReg tmp    = newVRegI(env);
          HReg src    = iselIntExpr_R(env, e->Iex.Binop.arg1);
-         PPC32RI* ri = iselIntExpr_RI(env, e->Iex.Binop.arg2);
-
-         if (ri->tag == Pri_Imm && ri->Pri.Imm.imm32 < 0x10000) {
-            addInstr(env, PPC32Instr_Alu32(aluOp, dst, src, ri));
-         } else {
-            addInstr(env, mk_iMOVds_RRI(env, tmp, ri));
-            addInstr(env, PPC32Instr_Alu32(aluOp, dst, src, PPC32RI_Reg(tmp)));
-         }
+         PPC32RI* ri = mk_FitRI16(env, iselIntExpr_RI(env, e->Iex.Binop.arg2));
+         addInstr(env, PPC32Instr_Alu32(aluOp, dst, src, ri));
          return dst;
       }
 //..       /* Could do better here; forcing the first arg into a reg
@@ -857,34 +874,31 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
 
       /* How about a div? */
       if (e->Iex.Binop.op == Iop_DivU32) {
-         HReg dst    = newVRegI(env);
-         HReg src1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
-         PPC32RI* ri = iselIntExpr_RI(env, e->Iex.Binop.arg2);
-         HReg src2;
-         if (ri->tag == Pri_Imm) {
-            src2 = newVRegI(env);
-            addInstr(env, mk_iMOVds_RRI(env, src2, ri));
-         } else {
-            src2 = ri->Pri.Reg.reg;
-         }
+         HReg dst  = newVRegI(env);
+         HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
+         HReg src2 = mk_RItoR(env, iselIntExpr_RI(env, e->Iex.Binop.arg2));
          addInstr(env, PPC32Instr_Div(False, dst, src1, src2));
          return dst;
       }
       if (e->Iex.Binop.op == Iop_DivS32) {
-         HReg dst    = newVRegI(env);
-         HReg src1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
-         PPC32RI* ri = iselIntExpr_RI(env, e->Iex.Binop.arg2);
-         HReg src2;
-         if (ri->tag == Pri_Imm) {
-            src2 = newVRegI(env);
-            addInstr(env, mk_iMOVds_RRI(env, src2, ri));
-         } else {
-            src2 = ri->Pri.Reg.reg;
-         }
+         HReg dst  = newVRegI(env);
+         HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
+         HReg src2 = mk_RItoR(env, iselIntExpr_RI(env, e->Iex.Binop.arg2));
          addInstr(env, PPC32Instr_Div(True, dst, src1, src2));
          return dst;
       }
 
+      /* No? Anyone for a mul? */
+      if (e->Iex.Binop.op == Iop_Mul16 ||
+          e->Iex.Binop.op == Iop_Mul32) {
+         Bool syned    = True;
+         HReg dst      = newVRegI(env);
+         HReg src1     = iselIntExpr_R(env, e->Iex.Binop.arg1);
+         PPC32RI* src2 = mk_FitRI16(env, iselIntExpr_RI(env, e->Iex.Binop.arg2));
+         addInstr(env, PPC32Instr_MulL(syned, 0, dst, src1, src2));
+         return dst;
+      }      
+
       /* Perhaps a shift op? */
       switch (e->Iex.Binop.op) {
       case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
@@ -1132,10 +1146,10 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
                            unop(Iop_64to32,
                                 binop(Iop_MullS32, bind(0), bind(1))));
             if (matchIRExpr(&mi,p_MullS32_then_64to32,e)) {
-               HReg dst = newVRegI(env);
-               HReg     src1 = iselIntExpr_R( env, mi.bindee[0] );
-               PPC32RI* src2 = iselIntExpr_RI( env, mi.bindee[1] );
-               addInstr(env, PPC32Instr_Alu32(Palu_MUL, dst, src1, src2));
+               HReg dst      = newVRegI(env);
+               HReg src1     = iselIntExpr_R( env, mi.bindee[0] );
+               PPC32RI* src2 = mk_FitRI16(env, iselIntExpr_RI( env, mi.bindee[1] ));
+               addInstr(env, PPC32Instr_MulL(True, 0, dst, src1, src2));
                return dst;
             }
          }
@@ -1150,10 +1164,10 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
                            unop(Iop_64to32,
                                 binop(Iop_MullU32, bind(0), bind(1))));
             if (matchIRExpr(&mi,p_MullU32_then_64to32,e)) {
-               HReg dst = newVRegI(env);
-               HReg     src1 = iselIntExpr_R( env, mi.bindee[0] );
-               PPC32RI* src2 = iselIntExpr_RI( env, mi.bindee[1] );
-               addInstr(env, PPC32Instr_Alu32(Palu_MUL, dst, src1, src2));
+               HReg dst      = newVRegI(env);
+               HReg src1     = iselIntExpr_R( env, mi.bindee[0] );
+               PPC32RI* src2 = mk_FitRI16(env, iselIntExpr_RI( env, mi.bindee[1] ));
+               addInstr(env, PPC32Instr_MulL(False, 0, dst, src1, src2));
                return dst;
             }
          }
@@ -1774,13 +1788,13 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
          /* get one operand into %r3, and the other into a R/I.
             Need to make an educated guess about which is better in
             which. */
-         HReg     tLo     = newVRegI(env);
-         HReg     tHi     = newVRegI(env);
-         Bool     syned   = e->Iex.Binop.op == Iop_MullS32;
-         HReg     rLeft   = iselIntExpr_R(env, e->Iex.Binop.arg1);
-         PPC32RI* riRight = iselIntExpr_RI(env, e->Iex.Binop.arg2);
-         addInstr(env, PPC32Instr_MulL(syned, 0, tLo, rLeft, riRight));
-         addInstr(env, PPC32Instr_MulL(syned, 1, tHi, rLeft, riRight));
+         HReg     tLo   = newVRegI(env);
+         HReg     tHi   = newVRegI(env);
+         Bool     syned = e->Iex.Binop.op == Iop_MullS32;
+         HReg     src1  = iselIntExpr_R(env, e->Iex.Binop.arg1);
+         PPC32RI* src2  = mk_FitRI16(env, iselIntExpr_RI(env, e->Iex.Binop.arg2));
+         addInstr(env, PPC32Instr_MulL(syned, 0, tLo, src1, src2));
+         addInstr(env, PPC32Instr_MulL(syned, 1, tHi, src1, src2));
          *rHi = tHi;
          *rLo = tLo;
          return;
@@ -3346,7 +3360,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
 
    /* --------- MEM FENCE --------- */
    case Ist_MFence:
-      addInstr(env, PPC32Instr_MFence(env->subarch));
+      addInstr(env, PPC32Instr_MFence());
       return;
 
    /* --------- EXIT --------- */