]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fill in many (most) x86 emission cases.
authorJulian Seward <jseward@acm.org>
Fri, 23 Jul 2004 01:34:11 +0000 (01:34 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 23 Jul 2004 01:34:11 +0000 (01:34 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@107

VEX/priv/host-x86/isel_x86.c
VEX/priv/host-x86/x86host_defs.c
VEX/priv/host-x86/x86host_defs.h

index 35a45f6873ff1b116d53c8b4c2ce4f3b473bb7fc..598bf2031dc580f1612fcd7d5ce41f07c20e97b0 100644 (file)
@@ -460,8 +460,7 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
        HReg dst = newVRegI(env);
        addInstr(env, mk_MOVsd_RR(rX,dst));
        HReg r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
-       addInstr(env, X86Instr_Alu32R(Xalu_TEST,
-                                     X86RMI_Imm(0xFF), r8));
+       addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
        addInstr(env, X86Instr_CMov32(Xcc_Z,r0,dst));
        return dst;
       }
@@ -766,7 +765,7 @@ static void iselIntExpr64 ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
          those regs are legitimately modifiable. */
       addInstr(env, X86Instr_Sh3232(Xsh_SHL, 0/*%cl*/, tHi, tLo));
       addInstr(env, X86Instr_Sh32(Xsh_SHL, 0/*%cl*/, X86RM_Reg(tLo)));
-      addInstr(env, X86Instr_Alu32R(Xalu_TEST, X86RMI_Imm(32), hregX86_ECX()));
+      addInstr(env, X86Instr_Test32(X86RI_Imm(32), X86RM_Reg(hregX86_ECX())));
       addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tLo), tHi));
       addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
       addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tLo));
index 97343f601115b76068aaecfd8e79607ac3c98f79..50bcd42b07fe228c7f09f084bf26ac9e2a05fa3b 100644 (file)
@@ -376,7 +376,6 @@ Char* showX86AluOp ( X86AluOp op ) {
    switch (op) {
       case Xalu_MOV:  return "mov";
       case Xalu_CMP:  return "cmp";
-      case Xalu_TEST: return "test";
       case Xalu_ADD:  return "add";
       case Xalu_SUB:  return "sub";
       case Xalu_ADC:  return "adc";
@@ -414,6 +413,22 @@ X86Instr* X86Instr_Alu32M ( X86AluOp op, X86RI* src, X86AMode* dst ) {
    i->Xin.Alu32M.op  = op;
    i->Xin.Alu32M.src = src;
    i->Xin.Alu32M.dst = dst;
+   vassert(op != Xalu_MUL);
+   return i;
+}
+X86Instr* X86Instr_Sh32 ( X86ShiftOp op, UInt src, X86RM* dst ) {
+   X86Instr* i     = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag          = Xin_Sh32;
+   i->Xin.Sh32.op  = op;
+   i->Xin.Sh32.src = src;
+   i->Xin.Sh32.dst = dst;
+   return i;
+}
+X86Instr* X86Instr_Test32  ( X86RI* src, X86RM* dst ) {
+   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag            = Xin_Test32;
+   i->Xin.Test32.src = src;
+   i->Xin.Test32.dst = dst;
    return i;
 }
 X86Instr* X86Instr_Unary32  ( X86UnaryOp op, X86RM* dst ) {
@@ -439,14 +454,6 @@ X86Instr* X86Instr_Div ( Bool syned, X86ScalarSz ssz, X86RM* src ) {
    i->Xin.Div.src     = src;
    return i;
 }
-X86Instr* X86Instr_Sh32 ( X86ShiftOp op, UInt src, X86RM* dst ) {
-   X86Instr* i     = LibVEX_Alloc(sizeof(X86Instr));
-   i->tag          = Xin_Sh32;
-   i->Xin.Sh32.op  = op;
-   i->Xin.Sh32.src = src;
-   i->Xin.Sh32.dst = dst;
-   return i;
-}
 X86Instr* X86Instr_Sh3232  ( X86ShiftOp op, UInt amt, HReg rHi, HReg rLo ) {
    X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
    i->tag            = Xin_Sh3232;
@@ -521,6 +528,20 @@ void ppX86Instr ( X86Instr* i ) {
          vex_printf(",");
          ppX86AMode(i->Xin.Alu32M.dst);
          return;
+      case Xin_Sh32:
+         vex_printf("%sl ", showX86ShiftOp(i->Xin.Sh32.op));
+         if (i->Xin.Sh32.src == 0)
+           vex_printf(" %%cl,"); 
+         else 
+            vex_printf(" $%d,", i->Xin.Sh32.src);
+         ppX86RM(i->Xin.Sh32.dst);
+         return;
+      case Xin_Test32:
+         vex_printf("testl ");
+         ppX86RI(i->Xin.Test32.src);
+         vex_printf(",");
+         ppX86RM(i->Xin.Test32.dst);
+         return;
       case Xin_Unary32:
          vex_printf("%sl ", showX86UnaryOp(i->Xin.Unary32.op));
          ppX86RM(i->Xin.Unary32.dst);
@@ -537,14 +558,6 @@ void ppX86Instr ( X86Instr* i ) {
                     showX86ScalarSz(i->Xin.Div.ssz));
          ppX86RM(i->Xin.Div.src);
          return;
-      case Xin_Sh32:
-         vex_printf("%sl ", showX86ShiftOp(i->Xin.Sh32.op));
-         if (i->Xin.Sh32.src == 0)
-           vex_printf(" %%cl,"); 
-         else 
-            vex_printf(" $%d,", i->Xin.Sh32.src);
-         ppX86RM(i->Xin.Sh32.dst);
-         return;
       case Xin_Sh3232:
          vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
          if (i->Xin.Sh3232.amt == 0)
@@ -612,8 +625,7 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i)
             addHRegUse(u, HRmWrite,  i->Xin.Alu32R.dst);
             return;
          }
-         if (i->Xin.Alu32R.op == Xalu_CMP 
-             || i->Xin.Alu32R.op == Xalu_TEST) {
+         if (i->Xin.Alu32R.op == Xalu_CMP) { 
             addHRegUse(u, HRmRead,  i->Xin.Alu32R.dst);
             return;
          }
@@ -623,6 +635,15 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i)
          addRegUsage_X86RI(u, i->Xin.Alu32M.src);
          addRegUsage_X86AMode(u, i->Xin.Alu32M.dst);
          return;
+      case Xin_Sh32:
+         addRegUsage_X86RM(u, i->Xin.Sh32.dst, HRmModify);
+         if (i->Xin.Sh32.src == 0)
+            addHRegUse(u, HRmRead, hregX86_ECX());
+         return;
+      case Xin_Test32:
+         addRegUsage_X86RI(u, i->Xin.Test32.src);
+         addRegUsage_X86RM(u, i->Xin.Test32.dst, HRmRead);
+         return;
       case Xin_Unary32:
          addRegUsage_X86RM(u, i->Xin.Unary32.dst, HRmModify);
          return;
@@ -636,11 +657,6 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i)
          addHRegUse(u, HRmModify, hregX86_EAX());
          addHRegUse(u, HRmModify, hregX86_EDX());
          return;
-      case Xin_Sh32:
-         addRegUsage_X86RM(u, i->Xin.Sh32.dst, HRmModify);
-         if (i->Xin.Sh32.src == 0)
-            addHRegUse(u, HRmRead, hregX86_ECX());
-         return;
       case Xin_Sh3232:
          addHRegUse(u, HRmRead, i->Xin.Sh3232.rLo);
          addHRegUse(u, HRmModify, i->Xin.Sh3232.rHi);
@@ -698,6 +714,13 @@ void mapRegs_X86Instr (HRegRemap* m, X86Instr* i)
          mapRegs_X86RI(m, i->Xin.Alu32M.src);
          mapRegs_X86AMode(m, i->Xin.Alu32M.dst);
          return;
+      case Xin_Sh32:
+         mapRegs_X86RM(m, i->Xin.Sh32.dst);
+         return;
+      case Xin_Test32:
+         mapRegs_X86RI(m, i->Xin.Test32.src);
+         mapRegs_X86RM(m, i->Xin.Test32.dst);
+         return;
       case Xin_Unary32:
          mapRegs_X86RM(m, i->Xin.Unary32.dst);
          return;
@@ -707,9 +730,6 @@ void mapRegs_X86Instr (HRegRemap* m, X86Instr* i)
       case Xin_Div:
          mapRegs_X86RM(m, i->Xin.Div.src);
          return;
-      case Xin_Sh32:
-         mapRegs_X86RM(m, i->Xin.Sh32.dst);
-         return;
       case Xin_Sh3232:
          mapReg(m, &i->Xin.Sh3232.rLo);
          mapReg(m, &i->Xin.Sh3232.rHi);
@@ -911,7 +931,7 @@ static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
 
 Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
 {
-   UInt opc, opc_rr, subopc_imm, opc_imma;
+   UInt opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
 
    UChar* p = &buf[0];
    vassert(nbuf >= 32);
@@ -945,7 +965,28 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
                goto bad;
          }
       }
-      /* ADD/SUB/ADC/SBB/AND/OR/XOR/TEST/CMP */
+      /* MUL */
+      if (i->Xin.Alu32R.op == Xalu_MUL) {
+       switch (i->Xin.Alu32R.src->tag) {
+case Xrmi_Reg:
+  *p++ = 0x0F;
+  *p++ = 0xAF;
+  p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.src->Xrmi.Reg.reg);
+  goto done;
+       case Xrmi_Imm:
+         if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
+           *p++ = 0x6B;
+           p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
+           *p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
+           goto done;
+         } else {
+           goto bad;
+         }
+
+       default: goto bad;
+       }
+      }
+      /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
       opc = opc_rr = subopc_imm = opc_imma = 0;
       switch (i->Xin.Alu32R.op) {
          case Xalu_ADD: opc = 0x03; opc_rr = 0x01; 
@@ -954,6 +995,12 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
                         subopc_imm = 5; opc_imma = 0x2D; break;
          case Xalu_AND: opc = 0x23; opc_rr = 0x21; 
                         subopc_imm = 4; opc_imma = 0x25; break;
+         case Xalu_XOR: opc = 0x33; opc_rr = 0x31; 
+                        subopc_imm = 6; opc_imma = 0x35; break;
+         case Xalu_OR:  opc = 0x0B; opc_rr = 0x09; 
+                        subopc_imm = 1; opc_imma = 0x0D; break;
+         case Xalu_CMP: opc = 0x3B; opc_rr = 0x39; 
+                        subopc_imm = 7; opc_imma = 0x3D; break;
          default: goto bad;
       }
       switch (i->Xin.Alu32R.src->tag) {
@@ -1006,7 +1053,8 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
                goto bad;
          }
       }
-      /* ADD/SUB/ADC/SBB/AND/OR/XOR/TEST/CMP */
+      /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP.  MUL is not
+         allowed here. */
       opc = subopc_imm = opc_imma = 0;
       switch (i->Xin.Alu32M.op) {
          case Xalu_ADD: opc = 0x01; subopc_imm = 0; break;
@@ -1036,7 +1084,66 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
       }
       break;
 
+   case Xin_Sh32:
+     opc_cl = opc_imm = subopc = 0;
+     switch (i->Xin.Sh32.op) {
+     case Xsh_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break;
+     case Xsh_SHL: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 4; break;
+     default: goto bad;
+     }
+     if (i->Xin.Sh32.src == 0) {
+       *p++ = opc_cl;
+       switch (i->Xin.Sh32.dst->tag) {
+       case Xrm_Reg:
+        p = doAMode_R(p, fake(subopc), i->Xin.Sh32.dst->Xrm.Reg.reg);
+        goto done;
+       default:
+        goto bad;
+       }
+     } else {
+       goto bad;
+     }
+     break;
+
+   case Xin_Test32:
+     if (i->Xin.Test32.src->tag == Xri_Imm
+         && i->Xin.Test32.dst->tag == Xrm_Reg) {
+       /* testl $imm32, %reg */
+       *p++ = 0xF7;
+       p = doAMode_R(p, fake(0), i->Xin.Test32.dst->Xrm.Reg.reg);
+       p = emit32(p, i->Xin.Test32.src->Xri.Imm.imm32);
+       goto done;
+     }
+     break;
+
+   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;
+       }
+     }
+     break;
+
+   case Xin_Push:
+     switch (i->Xin.Push.src->tag) {
+     case Xrmi_Mem: 
+       *p++ = 0xFF;
+       p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
+       goto done;
+     default: goto bad;
+     }
+
+   case Xin_Call:
+     *p++ = 0xFF;
+     p = doAMode_R(p, fake(2), i->Xin.Call.target);
+     goto done;
+
    case Xin_Goto:
+     /* unconditional jump to immediate */
       if (i->Xin.Goto.cond == Xcc_ALWAYS
           && i->Xin.Goto.dst->tag == Xri_Imm) {
          /* movl $immediate, %eax ; ret */
@@ -1044,17 +1151,109 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
          p = emit32(p, i->Xin.Goto.dst->Xri.Imm.imm32);
          *p++ = 0xC3;
          goto done;
-       }
+      }
+     /* unconditional jump to reg */
       if (i->Xin.Goto.cond == Xcc_ALWAYS
           && i->Xin.Goto.dst->tag == Xri_Reg) {
          /* movl %reg, %eax ; ret */
-         *p++ = 0x89;
-        p = doAMode_R(p, i->Xin.Goto.dst->Xri.Reg.reg, hregX86_EAX());
+         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());
+          }
+          *p++ = 0xC3;
+          goto done;
+       }
+     /* conditional jump to immediate */
+      if (i->Xin.Goto.cond != Xcc_ALWAYS
+          && i->Xin.Goto.dst->tag == Xri_Imm) {
+       /* jmp fwds if !condition */
+       *p++ = 0x70 + (i->Xin.Goto.cond ^ 1);
+       *p++ = 6; /* # of bytes in the next bit */
+         /* movl $immediate, %eax ; ret */
+         *p++ = 0xB8;
+         p = emit32(p, i->Xin.Goto.dst->Xri.Imm.imm32);
          *p++ = 0xC3;
          goto done;
-       }
+      }
+      break;
 
+   case Xin_CMov32:
+     vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
+     *p++ = 0x0F;
+     *p++ = 0x40 + i->Xin.CMov32.cond;
+     if (i->Xin.CMov32.src->tag == Xrm_Reg) {
        goto bad;
+     }
+     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;
+     }
+     break;
+
+   case Xin_LoadEX:
+     if (i->Xin.LoadEX.szSmall == 1 && !i->Xin.LoadEX.syned) {
+       /* movzbl */
+       *p++ = 0x0F;
+       *p++ = 0xB6;
+       p = doAMode_M(p, i->Xin.LoadEX.dst, i->Xin.LoadEX.src); 
+       goto done;
+     }
+     if (i->Xin.LoadEX.szSmall == 2 && !i->Xin.LoadEX.syned) {
+       /* movzwl */
+       *p++ = 0x0F;
+       *p++ = 0xB7;
+       p = doAMode_M(p, i->Xin.LoadEX.dst, i->Xin.LoadEX.src); 
+       goto done;
+     }
+     break;
+
+   case Xin_Store:
+     if (i->Xin.Store.sz == 1) {
+       /* we have to do complex dodging and weaving if
+         src is not the low 8 bits of %eax/%ebx/%ecx/%edx. */
+       if (iregNo(i->Xin.Store.src) < 4) {
+        /* we're OK, can do it directly */
+        *p++ = 0x88;
+        p = doAMode_M(p, i->Xin.Store.src, i->Xin.Store.dst);
+        goto done;
+       } else {
+        /* bleh.  This means the source is %edi or %esi.  Since the
+address mode can only mention three registers, at least one of 
+%eax/%ebx/%ecx/%edx
+must be available to temporarily swap the source into, so the
+store can happen. */
+        HReg eax = hregX86_EAX(), ebx = hregX86_EBX(), ecx = hregX86_ECX(), edx = hregX86_EDX();
+        Bool a_ok = True, b_ok = True, c_ok = True, d_ok = True;
+        HRegUsage u;
+        Int j;
+   initHRegUsage(&u);
+      addRegUsage_X86AMode(&u,  i->Xin.Store.dst);
+      for (j = 0; j < u.n_used; j++) {
+       HReg r = u.hreg[j];
+       if (r == eax) a_ok = False;
+       if (r == ebx) b_ok = False;
+       if (r == ecx) c_ok = False;
+       if (r == edx) d_ok = False;
+      }
+      HReg swap = INVALID_HREG;
+      if (a_ok) swap = eax;
+      if (b_ok) swap = ebx;
+      if (c_ok) swap = ecx;
+      if (d_ok) swap = edx;
+      vassert(swap != INVALID_HREG);
+      /* xchgl %source, %swap */
+      *p++ = 0x87;
+      p = doAMode_R(p, i->Xin.Store.src, swap);
+      /* movb lo8{%swap}, (dst) */
+        *p++ = 0x88;
+        p = doAMode_M(p, swap, i->Xin.Store.dst);
+      /* xchgl %source, %swap */
+      *p++ = 0x87;
+      p = doAMode_R(p, i->Xin.Store.src, swap);
+      goto done;
+       }
+     }
+     break;
 
    default: 
       goto bad;
index 371408319413064dae432761309a2a6bc1446e35..c48716bdca0ca3deea3447970bb7661ca85493cf 100644 (file)
@@ -221,7 +221,6 @@ typedef
       Xalu_INVALID,
       Xalu_MOV,
       Xalu_CMP,
-      Xalu_TEST,
       Xalu_ADD, Xalu_SUB, Xalu_ADC, Xalu_SBB, 
       Xalu_AND, Xalu_OR, Xalu_XOR,
       Xalu_MUL
@@ -248,10 +247,11 @@ typedef
    enum {
       Xin_Alu32R,    /* 32-bit mov/arith/logical, dst=REG */
       Xin_Alu32M,    /* 32-bit mov/arith/logical, dst=MEM */
+      Xin_Sh32,      /* 32-bit shift/rotate, dst=REG or MEM */
+      Xin_Test32,    /* 32-bit test (AND, set flags, discard result) */
       Xin_Unary32,   /* 32-bit not and neg */
       Xin_MulL,      /* widening multiply */
       Xin_Div,       /* div and mod */
-      Xin_Sh32,      /* 32-bit shift/rotate, dst=REG or MEM */
       Xin_Sh3232,    /* shldl or shrdl */
       Xin_Push,      /* push (32-bit?) value on stack */
       Xin_Call,      /* call to address in register */
@@ -278,10 +278,19 @@ typedef
             X86RI*    src;
             X86AMode* dst;
          } Alu32M;
+         struct {
+            X86ShiftOp op;
+            UInt       src;  /* shift amount, or 0 means %cl */
+            X86RM*     dst;
+         } Sh32;
+         struct {
+            X86RI* src;
+            X86RM* dst;
+         } Test32;
          /* Not and Neg */
          struct {
             X86UnaryOp op;
-            X86RM*    dst;
+            X86RM*     dst;
          } Unary32;
          /* DX:AX = AX *s/u r/m16,  or EDX:EAX = EAX *s/u r/m32 */
          struct {
@@ -295,17 +304,12 @@ typedef
             X86ScalarSz ssz;
             X86RM*      src;
          } Div;
-         struct {
-            X86ShiftOp op;
-            UInt       src;  /* shift amount, or 0 means %cl */
-            X86RM*     dst;
-         } Sh32;
          /* shld/shrd.  op may only be Xsh_SHL or Xsh_SHR */
          struct {
             X86ShiftOp op;
-            UInt amt;   /* shift amount, or 0 means %cl */
-            HReg rHi;
-            HReg rLo;
+            UInt       amt;   /* shift amount, or 0 means %cl */
+            HReg       rHi;
+            HReg       rLo;
          } Sh3232;
          struct {
             X86RMI* src;
@@ -323,8 +327,8 @@ typedef
             be the bogus Xcc_ALWAYS. */
          struct {
             X86CondCode cond;
-            X86RM* src;
-            HReg   dst;
+            X86RM*      src;
+            HReg        dst;
          } CMov32;
          /* Sign/Zero extending loads.  Dst size is always 32 bits. */
          struct {
@@ -336,8 +340,8 @@ typedef
          /* 16/8 bit stores, which are troublesome (particularly
             8-bit) */
          struct {
-            UChar sz; /* only 1 or 2 */
-            HReg src;
+            UChar     sz; /* only 1 or 2 */
+            HReg      src;
             X86AMode* dst;
          } Store;
       } Xin;
@@ -347,9 +351,10 @@ typedef
 extern X86Instr* X86Instr_Alu32R  ( X86AluOp, X86RMI*, HReg );
 extern X86Instr* X86Instr_Alu32M  ( X86AluOp, X86RI*,  X86AMode* );
 extern X86Instr* X86Instr_Unary32 ( X86UnaryOp op, X86RM* dst );
+extern X86Instr* X86Instr_Sh32    ( X86ShiftOp, UInt, X86RM* );
+extern X86Instr* X86Instr_Test32  ( X86RI* src, X86RM* dst );
 extern X86Instr* X86Instr_MulL    ( Bool syned, X86ScalarSz, X86RM* );
 extern X86Instr* X86Instr_Div     ( Bool syned, X86ScalarSz, X86RM* );
-extern X86Instr* X86Instr_Sh32    ( X86ShiftOp, UInt, X86RM* );
 extern X86Instr* X86Instr_Sh3232  ( X86ShiftOp, UInt amt, HReg rHi, HReg rLo );
 extern X86Instr* X86Instr_Push    ( X86RMI* );
 extern X86Instr* X86Instr_Call    ( HReg );