]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
More instr emitting:
authorCerion Armour-Brown <cerion@valgrind.org>
Wed, 16 Feb 2005 10:25:26 +0000 (10:25 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Wed, 16 Feb 2005 10:25:26 +0000 (10:25 +0000)
 - most 'forms' done
 - had a go at Pin_Call, Pin_Goto

Changed CondTest & added invertCondTest()

Fixed Div - only takes reg operands

Fixed iselIntExpr_R_wrk: alu32, div, shft - dtrt with large immediates

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

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

index bb28e5b42ea356eec2d4e85b6ba3c0f8afbf282c..ae44e9be6ee2ea532d281551de97866b9f765d8a 100644 (file)
@@ -227,6 +227,13 @@ HChar* showPPC32CondCode ( PPC32CondCode cond )
    }
 }
 
+PPC32CondTest invertCondTest ( PPC32CondTest ct )
+{
+   vassert(ct != Pct_ALWAYS);
+   return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
+}
+
+
 /* --------- PPCAMode: memory address expressions. --------- */
 
 PPC32AMode* PPC32AMode_IR ( UInt idx, HReg base ) {
@@ -436,6 +443,8 @@ HChar* showPPC32CmpOp ( PPC32CmpOp op ) {
 //.. }
 
 PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg src1, PPC32RI* src2 ) {
+   if (src2->tag == Pri_Imm)
+      vassert(src2->Pri.Imm.imm32 < 0x10000);
    PPC32Instr* i     = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag            = Pin_Alu32;
    i->Pin.Alu32.op   = op;
@@ -492,8 +501,7 @@ PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
    i->Pin.MulL.src2  = src2;
    return i;
 }
-PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst,
-                             HReg src1, PPC32RI* src2 ) {
+PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg src1, HReg src2 ) {
    PPC32Instr* i        = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag             = Pin_Div;
    i->Pin.Div.syned   = syned;
@@ -740,11 +748,11 @@ void ppPPC32Instr ( PPC32Instr* i )
    case Pin_Div:
       vex_printf("divw%s ",
                  i->Pin.Div.syned ? "" : "u");
-      ppHRegPPC32(i->Pin.MulL.dst);
+      ppHRegPPC32(i->Pin.Div.dst);
       vex_printf(",");
-      ppHRegPPC32(i->Pin.MulL.src1);
+      ppHRegPPC32(i->Pin.Div.src1);
       vex_printf(",");
-      ppPPC32RI(i->Pin.MulL.src2);
+      ppHRegPPC32(i->Pin.Div.src2);
       return;
 //..       case Xin_Sh3232:
 //..          vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
@@ -761,19 +769,13 @@ void ppPPC32Instr ( PPC32Instr* i )
 //..          ppX86RMI(i->Xin.Push.src);
 //..          return;
    case Pin_Call:
-// CAB: Add representation of BO to Pin_Call...
-// 001xx => branch if false
-// 011xx => branch if true
-// 1x100 => branch always
-      
-// bcl false|true,cond,target
-      vex_printf("bcl (%s)[%d] ",
-                 showPPC32CondCode(i->Pin.Call.cond), 
-                 i->Pin.Call.regparms);
-      vex_printf("0x%x", i->Pin.Call.target);
+      vex_printf("call: la r12, 0x%x ; mtctr r12 ; bcctrl[%d] %s,reg",
+                 i->Pin.Call.target,
+                 i->Pin.Call.regparms,
+                 showPPC32CondCode(i->Pin.Call.cond));
       break;
    case Pin_Goto:
-// bc false|true,cond,target
+      vex_printf("goto: ");
       if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
          vex_printf("if (%%CR.%s) { ", 
                     showPPC32CondCode(i->Pin.Goto.cond));
@@ -783,8 +785,7 @@ void ppPPC32Instr ( PPC32Instr* i )
          ppIRJumpKind(i->Pin.Goto.jk);
          vex_printf(" ; ");
       }
-      vex_printf("bc ");
-      vex_printf("%%r4, ");
+      vex_printf("bca %s,%%r4, ", showPPC32CondCode(i->Pin.Goto.cond));
       ppPPC32RI(i->Pin.Goto.dst);
       vex_printf(" ; ret");
       if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
@@ -1030,7 +1031,7 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
    case Pin_Div:
       addHRegUse(u, HRmWrite, i->Pin.Div.dst);
       addHRegUse(u, HRmRead, i->Pin.Div.src1);
-      addRegUsage_PPC32RI(u, i->Pin.Div.src2);
+      addHRegUse(u, HRmRead, i->Pin.Div.src2);
       return;
 //..       case Xin_Sh3232:
 //..          addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
@@ -1261,7 +1262,7 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
    case Pin_Div:
       mapReg(m, &i->Pin.Div.dst);
       mapReg(m, &i->Pin.Div.src1);
-      mapRegs_PPC32RI(m, i->Pin.Div.src2);
+      mapReg(m, &i->Pin.Div.src2);
       return;
 //..       case Xin_Sh3232:
 //..          mapReg(m, &i->Xin.Sh3232.src);
@@ -1734,13 +1735,94 @@ static UChar* mkFormXO ( UChar* p, UInt op1, UInt r1, UInt r2,
    vassert(r2  < 0x20);
    vassert(r3  < 0x20);
    vassert(b10 < 0x2);
-   vassert(op2 < 0x400);
+   vassert(op2 < 0x200);
    vassert(b0  < 0x2);
    UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
                     (r3<<11) | (b10 << 10) | (op2<<1) | (b0));
    return emit32(p, theInstr);
 }
 
+static UChar* mkFormXL ( UChar* p, UInt op1, UInt f1, UInt f2,
+                         UInt f3, UInt op2, UInt b0 )
+{
+   vassert(op1 < 0x40);
+   vassert(f1  < 0x20);
+   vassert(f2  < 0x20);
+   vassert(f3  < 0x20);
+   vassert(op2 < 0x400);
+   vassert(b0  < 0x2);
+   UInt theInstr = ((op1<<26) | (f1<<21) | (f2<<16) |
+                    (f3<<11) | (op2<<1) | (b0));
+   return emit32(p, theInstr);
+}
+
+// Note: for split field ops, give mnemonic arg
+static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt op2 )
+{
+   vassert(r1  < 0x20);
+   vassert(f2  < 0x20);
+   vassert(op2 < 0x400);
+   switch (op2) {
+   case 144:  // mtcrf
+      vassert(f2 < 0x100);
+      f2 = f2 << 1;
+      break;
+   case 339:  // mfspr
+   case 371:  // mftb
+   case 467:  // mtspr
+      vassert(f2 < 0x400);
+      f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);  // re-arrange split field
+      break;
+   default: vpanic("mkFormXFX(PPC32)");
+   }
+   UInt theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (op2<<1));
+   return emit32(p, theInstr);
+}
+
+#if 0
+// 'b'
+static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
+{
+   vassert(LI  < 0x1000000);
+   vassert(AA  < 0x2);
+   vassert(LK  < 0x2);
+   UInt theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
+   return emit32(p, theInstr);
+}
+#endif
+
+// 'bc'
+static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
+                        UInt BD, UInt AA, UInt LK )
+{
+   vassert(BO  < 0x20);
+   vassert(BI  < 0x20);
+   vassert(BD  < 0x4000);
+   vassert(AA  < 0x2);
+   vassert(LK  < 0x2);
+   UInt theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
+                    (BD<<2) | (AA<<1) | (LK));
+   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 )
+{
+   vassert(op1 < 0x40);
+   vassert(r1  < 0x20);
+   vassert(r2  < 0x20);
+   vassert(f3  < 0x20);
+   vassert(MB  < 0x20);
+   vassert(ME  < 0x20);
+   vassert(Rc  < 0x2);
+   UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
+                    (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
+   return emit32(p, theInstr);
+}
+#endif
+
 static UChar* doAMode_IR ( UChar* p, UInt op1, HReg hrSD, PPC32AMode* am )
 {
    vassert(am->tag == Pam_IR);
@@ -1881,30 +1963,30 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
    }
 
    case Pin_Sh32: {
-      UInt op1 = 31, op2, rB, imm;
+      UInt opc1 = 31, opc2, rB, sh;
       UInt op = i->Pin.Sh32.op;
-      UInt rD = iregNo(i->Pin.Alu32.dst);
-      UInt rA = iregNo(i->Pin.Alu32.src1);
-      PPC32RITag ri_tag = i->Pin.Alu32.src2->tag;
+      UInt rS = iregNo(i->Pin.Sh32.dst);
+      UInt rA = iregNo(i->Pin.Sh32.src);
+      PPC32RITag ri_tag = i->Pin.Sh32.shft->tag;
 
       if ((op == Psh_SHL || op == Psh_SHR) && ri_tag == Pri_Imm)
          goto bad;  // No imm versions of these
 
       switch (op) {
-      case Psh_SHL: op2 = 24;  break;
-      case Psh_SHR: op2 = 536; break;
-      case Psh_SAR: op2 = (ri_tag == Pri_Reg) ? 792 : 824; break;
+      case Psh_SHL: opc2 = 24;  break;
+      case Psh_SHR: opc2 = 536; break;
+      case Psh_SAR: opc2 = (ri_tag == Pri_Reg) ? 792 : 824; break;
       default: goto bad;
       }
 
       switch (i->Pin.Sh32.shft->tag) {
       case Pri_Reg:
-         rB = iregNo(i->Pin.Alu32.src2->Pri.Reg.reg);
-         p = mkFormX(p, op1, rD, rA, rB, op2, 0);
+         rB = iregNo(i->Pin.Sh32.shft->Pri.Reg.reg);
+         p = mkFormX(p, opc1, rS, rA, rB, opc2, 0);
          break;
       case Pri_Imm:
-         imm = i->Pin.Alu32.src2->Pri.Imm.imm32;
-         p = mkFormX(p, op1, rD, rA, imm, op2, 0);
+         sh = i->Pin.Sh32.shft->Pri.Imm.imm32;
+         p = mkFormX(p, opc1, rS, rA, sh, opc2, 0);
          break;
       default:
          goto bad;
@@ -1923,9 +2005,8 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 //..       }
 //..       break;
 
-//..   case Pin_Cmp32:
-//..      //...
-//..      break;
+//..    case Pin_Cmp32:
+//..       goto done;
 
 //..    case Xin_Unary32:
 //..       if (i->Xin.Unary32.op == Xun_NOT) {
@@ -2018,99 +2099,104 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 //..             goto bad;
 //..       }
 
-   case Pin_Call:
+   case Pin_Call: {
+      Addr32 target;
+
       /* As per detailed comment for Ain_Call in
          getRegUsage_PPC32Instr above, %r12 is used as an address
          temporary. */
       /* jump over the following two insns if the condition does not
          hold */
       if (i->Pin.Call.cond.test != Pct_ALWAYS) {
+         target = 16; /* num bytes in next insts */
+         /* bca ct,cf,target */
+         p = mkFormB(p, invertCondTest(i->Pin.Call.cond.test),
+                     (31 - i->Pin.Call.cond.flag),
+                     target, 1, 0);
+      }
+
+      /* addi r12,0,(target & 0xFFFF)
+         addis r12,r12,((target >> 16) & 0xFFFF) => load target to r12 */
+      target = i->Pin.Call.target;
+      p = mkFormD(p, 14, 12, 0, (target & 0xFFFF));
+      p = mkFormD(p, 15, 12, 12, ((target>>16) & 0xFFFF) );
+
+      /* mtspr 9,r12 => move r12 to count register */
+      p = mkFormXFX(p, 12, 9, 467);
+      
+      /* bcctrl 20,0 => branch w. link to count register */
+      p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);
+
+/* CAB: Hmm...
+   "When possible, independent instructions should separate the load
+   of the Count Register from the branch to prevent pipeline stalls." */
+
+      goto done;
+   }
 
-//..          *p++ = 0x70 + (0xF & (i->Pin.Call.cond ^ 1));
-//..          *p++ = 16; /* 16 bytes in the next two insns */
+   case Pin_Goto: {
+      UInt magic_num = 0;
+      UChar r_dst, r_src;
+      PPC32CondCode cond = i->Pin.Goto.cond;
+      UInt imm;
+      
+      /* First off, if this is conditional, create a conditional
+         jump over the rest of it. */
+      if (cond.test != Pct_ALWAYS) {
+         /* jmp fwds if !condition */
+         imm = 8; /* num bytes in next insts */
+         /* bca ct,cf,imm */
+         p = mkFormB(p, invertCondTest(cond.test),
+                     (31 - cond.flag), imm, 1, 0);
       }
 
-      /* la $target, %r12 */
-//..       *p++ = 0x49;
-//..       *p++ = 0xBB;
-//..       p = emit32(p, i->Ain.Call.target);
+      /* If a non-boring, set GuestStatePtr appropriately. */
+      /* addi r31,0,magic_num */
+      switch (i->Pin.Goto.jk) {
+      case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break;
+      case Ijk_Syscall:   magic_num = VEX_TRC_JMP_SYSCALL;   break;
+      case Ijk_Yield:     magic_num = VEX_TRC_JMP_YIELD;     break;
+      case Ijk_EmWarn:    magic_num = VEX_TRC_JMP_EMWARN;    break;
+      case Ijk_MapFail:   magic_num = VEX_TRC_JMP_MAPFAIL;   break;
+      case Ijk_NoDecode:  magic_num = VEX_TRC_JMP_NODECODE;  break;
+      case Ijk_Ret:
+      case Ijk_Call:
+      case Ijk_Boring:
+         break;
+      default: 
+         ppIRJumpKind(i->Pin.Goto.jk);
+         vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
+      }
+      if (magic_num !=0) {
+         vassert(magic_num < 0x10000);
+         p = mkFormD(p, 14, 31, 0, magic_num);
+      }
 
-      /* call *%r12 */
-//..       *p++ = 0x41;
-//..       *p++ = 0xFF;
-//..       *p++ = 0xD3;
 
-//      goto done;
-      goto bad;
+      /* Get the destination address into %r4 */
+// 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));
+      } else {
+         vassert(i->Pin.Goto.dst->tag == Pri_Reg);
+         if (i->Pin.Goto.dst->Pri.Reg.reg != hregPPC32_GPR4()) {
+            /* add r_dst, 0, r_src */
+            r_src = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
+            p = mkFormXO(p, 31, r_dst, 0, r_src, 0, 266, 0);
+            /* noop */
+            p = mkFormD(p, 24, 0, 0, 0);
+         }
+      }
 
-//..    case Xin_Goto:
-//..       /* Use ptmp for backpatching conditional jumps. */
-//..       ptmp = NULL;
-//.. 
-//..       /* First off, if this is conditional, create a conditional
-//..          jump over the rest of it. */
-//..       if (i->Xin.Goto.cond != Xcc_ALWAYS) {
-//..          /* jmp fwds if !condition */
-//..          *p++ = 0x70 + (i->Xin.Goto.cond ^ 1);
-//..          ptmp = p; /* fill in this bit later */
-//..          *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
-//..       }
-//.. 
-//..       /* If a non-boring, set %ebp (the guest state pointer)
-//..          appropriately. */
-//..       /* movl $magic_number, %ebp */
-//..       switch (i->Xin.Goto.jk) {
-//..          case Ijk_ClientReq: 
-//..             *p++ = 0xBD;
-//..             p = emit32(p, VEX_TRC_JMP_CLIENTREQ); break;
-//..          case Ijk_Syscall: 
-//..             *p++ = 0xBD;
-//..             p = emit32(p, VEX_TRC_JMP_SYSCALL); break;
-//..          case Ijk_Yield: 
-//..             *p++ = 0xBD;
-//..             p = emit32(p, VEX_TRC_JMP_YIELD); break;
-//..          case Ijk_EmWarn:
-//..             *p++ = 0xBD;
-//..             p = emit32(p, VEX_TRC_JMP_EMWARN); break;
-//..          case Ijk_MapFail:
-//..             *p++ = 0xBD;
-//..             p = emit32(p, VEX_TRC_JMP_MAPFAIL); break;
-//..          case Ijk_NoDecode:
-//..             *p++ = 0xBD;
-//..             p = emit32(p, VEX_TRC_JMP_NODECODE); break;
-//..          case Ijk_Ret:
-//..    case Ijk_Call:
-//..          case Ijk_Boring:
-//..             break;
-//..          default: 
-//..             ppIRJumpKind(i->Xin.Goto.jk);
-//..             vpanic("emit_X86Instr.Xin_Goto: unknown jump kind");
-//..       }
-//.. 
-//..       /* Get the destination address into %eax */
-//..       if (i->Xin.Goto.dst->tag == Xri_Imm) {
-//..          /* movl $immediate, %eax ; ret */
-//..          *p++ = 0xB8;
-//..          p = emit32(p, i->Xin.Goto.dst->Xri.Imm.imm32);
-//..       } else {
-//..          vassert(i->Xin.Goto.dst->tag == Xri_Reg);
-//..          /* movl %reg, %eax ; ret */
-//..          if (i->Xin.Goto.dst->Xri.Reg.reg != hregX86_EAX()) {
-//..             *p++ = 0x89;
-//..             p = doAMode_R(p, i->Xin.Goto.dst->Xri.Reg.reg, hregX86_EAX());
-//..          }
-//..       }
-//.. 
-//..       /* ret */
-//..       *p++ = 0xC3;
-//.. 
-//..       /* Fix up the conditional jump, if there was one. */
-//..       if (i->Xin.Goto.cond != Xcc_ALWAYS) {
-//..          Int delta = p - ptmp;
-//..          vassert(delta > 0 && delta < 20);
-//..          *ptmp = (UChar)(delta-1);
-//..       }
-//..       goto done;
+      /* ret => bclr (always),0 */
+      p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0);
+      goto done;
+   }
 
 //..    case Xin_CMov32:
 //..       vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
index 7507060170239de9048158451577c954a3fc4baa..8708d32433e1a599406f315d8ed7a046aea7dfa6 100644 (file)
@@ -179,12 +179,14 @@ typedef
 
 typedef
    enum {   /* Reflects bc bitfield BO */
-      Pct_TRUE   = 0,
-      Pct_FALSE  = 1,
-      Pct_ALWAYS = 2
+      Pct_FALSE  = 0x4,
+      Pct_TRUE   = 0xC,
+      Pct_ALWAYS = 0x14
    }
    PPC32CondTest;
 
+extern PPC32CondTest invertCondTest ( PPC32CondTest );
+
 typedef
    struct {
       PPC32CondFlag flag;
@@ -197,6 +199,7 @@ extern HChar* showPPC32CondCode ( PPC32CondCode );
 
 
 
+
 /* --------- Memory address expressions (amodes). --------- */
 
 typedef
@@ -415,10 +418,10 @@ typedef
          } MulL;
          /* ppc32 div/idiv instruction.  Modifies EDX and EAX and reads src. */
          struct {
-            Bool     syned;
-            HReg     dst;
-            HReg     src1;
-            PPC32RI* src2;
+            Bool syned;
+            HReg dst;
+            HReg src1;
+            HReg src2;
          } Div;
 //..          /* shld/shrd.  op may only be Xsh_SHL or Xsh_SHR */
 //..          struct {
@@ -559,7 +562,7 @@ extern PPC32Instr* PPC32Instr_Sh32      ( PPC32ShiftOp, HReg, HReg, PPC32RI* );
 extern PPC32Instr* PPC32Instr_Cmp32     ( PPC32CmpOp, UInt, HReg, PPC32RI* );
 extern PPC32Instr* PPC32Instr_Unary32   ( PPC32UnaryOp op, HReg dst, HReg src );
 extern PPC32Instr* PPC32Instr_MulL      ( Bool syned, Bool word, HReg, HReg, PPC32RI* );
-extern PPC32Instr* PPC32Instr_Div       ( Bool syned, HReg, HReg, PPC32RI* );
+extern PPC32Instr* PPC32Instr_Div       ( Bool syned, HReg dst, HReg src1, HReg src2 );
 //.. extern X86Instr* X86Instr_Sh3232    ( X86ShiftOp, UInt amt, HReg src, HReg dst );
 //.. extern X86Instr* X86Instr_Push      ( X86RMI* );
 extern PPC32Instr* PPC32Instr_Call      ( PPC32CondCode, Addr32, Int );
index 78c9113a7ca19a0fd90d6ff6f12dba973647d1bc..9a9b908a32d4210a0090265ae44020c532ac3d13 100644 (file)
@@ -825,9 +825,16 @@ 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);
-         addInstr(env, PPC32Instr_Alu32(aluOp, dst, src, ri));
+
+         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)));
+         }
          return dst;
       }
 //..       /* Could do better here; forcing the first arg into a reg
@@ -850,17 +857,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_src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2);
-         addInstr(env, PPC32Instr_Div(False, dst, src1, ri_src2));
+         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;
+         }
+         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_src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2);
-         addInstr(env, PPC32Instr_Div(True, dst, src1, ri_src2));
+         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;
+         }
+         addInstr(env, PPC32Instr_Div(True, dst, src1, src2));
          return dst;
       }
 
@@ -900,9 +921,10 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          default: break;
          }
 
-         /* Now consider the shift amount.  If it's a literal, we
+         /* Now consider the shift amount.  If it's a small literal, we
             can do a much better job than the general case. */
-         if (e->Iex.Binop.arg2->tag == Iex_Const) {
+         if (e->Iex.Binop.arg2->tag == Iex_Const &&
+             e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 < 32) {
             /* assert that the IR is well-typed */
             Int nshift;
             vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
@@ -1339,7 +1361,7 @@ static PPC32AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e )
       return PPC32AMode_IR(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
                            iselIntExpr_R(env,  e->Iex.Binop.arg1));
    }
-
+      
    /* Add32(expr,expr) */
    if (e->tag == Iex_Binop 
        && e->Iex.Binop.op == Iop_Add32) {
@@ -1446,7 +1468,7 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
       /* Generate code for the arg, and negate the test condition */
       PPC32CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
       vassert(cond.test != Pct_ALWAYS);
-      cond.test = cond.test ^ 1;
+      cond.test = invertCondTest(cond.test);
       return cond;
    }