]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Generate better ucode for back-to-back sequences of register pushes and
authorJulian Seward <jseward@acm.org>
Tue, 7 May 2002 23:38:30 +0000 (23:38 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 7 May 2002 23:38:30 +0000 (23:38 +0000)
pops, as appear at function prologues/epilogues.  Specifically, update %ESP
just once for the whole sequence.  This reduces by about 20% the number
of calls to handle_esp_assignment (for kate in KDE 3.0, -O), which is a
good thing since that is quite expensive.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@227

coregrind/vg_memory.c
coregrind/vg_to_ucode.c
vg_memory.c
vg_to_ucode.c

index 59d183b48a4fa327b9660e640a367a8072d8baf3..a6a2c5d92962bfd740a1b8c07d49ceb52db4108d 100644 (file)
@@ -99,7 +99,7 @@
 
 #ifdef VG_PROFILE_MEMORY
 
-#define N_PROF_EVENTS 120
+#define N_PROF_EVENTS 150
 
 static UInt event_ctr[N_PROF_EVENTS];
 
@@ -204,16 +204,23 @@ static void init_prof_mem ( void ) { }
    101  handle_esp_assignment
    102  handle_esp_assignment(-4)
    103  handle_esp_assignment(+4)
-   104  handle_esp_assignment(+16)
-   105  handle_esp_assignment(-12)
-   106  handle_esp_assignment(+8)
-   107  handle_esp_assignment(-8)
-
-   110  vg_handle_esp_assignment_SLOWLY
-   111  vg_handle_esp_assignment_SLOWLY(normal; move down)
-   112  vg_handle_esp_assignment_SLOWLY(normal; move up)
-   113  vg_handle_esp_assignment_SLOWLY(normal)
-   114  vg_handle_esp_assignment_SLOWLY(>= HUGE_DELTA)
+   104  handle_esp_assignment(-12)
+   105  handle_esp_assignment(-8)
+   106  handle_esp_assignment(+16)
+   107  handle_esp_assignment(+12)
+   108  handle_esp_assignment(0)
+   109  handle_esp_assignment(+8)
+   110  handle_esp_assignment(-16)
+   111  handle_esp_assignment(+20)
+   112  handle_esp_assignment(-20)
+   113  handle_esp_assignment(+24)
+   114  handle_esp_assignment(-24)
+
+   120  vg_handle_esp_assignment_SLOWLY
+   121  vg_handle_esp_assignment_SLOWLY(normal; move down)
+   122  vg_handle_esp_assignment_SLOWLY(normal; move up)
+   123  vg_handle_esp_assignment_SLOWLY(normal)
+   124  vg_handle_esp_assignment_SLOWLY(>= HUGE_DELTA)
 */
 
 /*------------------------------------------------------------*/
@@ -712,7 +719,6 @@ static __inline__ UInt shiftRight16 ( UInt x )
    Under all other circumstances, it defers to the relevant _SLOWLY
    function, which can handle all situations.
 */
-
 UInt VG_(helperc_LOADV4) ( Addr a )
 {
 #  ifdef VG_DEBUG_MEMORY
@@ -1384,9 +1390,23 @@ void VGM_(handle_esp_assignment) ( Addr new_espA )
          return;
       }
 
-      if (delta == 16) {
-         /* Also surprisingly common. */
+      if (delta == -12) {
          PROF_EVENT(104);
+         make_aligned_word_WRITABLE(new_esp);
+         make_aligned_word_WRITABLE(new_esp+4);
+         make_aligned_word_WRITABLE(new_esp+8);
+         return;
+      }
+
+      if (delta == -8) {
+         PROF_EVENT(105);
+         make_aligned_word_WRITABLE(new_esp);
+         make_aligned_word_WRITABLE(new_esp+4);
+         return;
+      }
+
+      if (delta == 16) {
+         PROF_EVENT(106);
          make_aligned_word_NOACCESS(old_esp);
          make_aligned_word_NOACCESS(old_esp+4);
          make_aligned_word_NOACCESS(old_esp+8);
@@ -1394,27 +1414,77 @@ void VGM_(handle_esp_assignment) ( Addr new_espA )
          return;
       }
 
-      if (delta == -12) {
-         PROF_EVENT(105);
+      if (delta == 12) {
+         PROF_EVENT(107);
+         make_aligned_word_NOACCESS(old_esp);
+         make_aligned_word_NOACCESS(old_esp+4);
+         make_aligned_word_NOACCESS(old_esp+8);
+         return;
+      }
+
+      if (delta == 0) {
+         PROF_EVENT(108);
+         return;
+      }
+
+      if (delta == 8) {
+         PROF_EVENT(109);
+         make_aligned_word_NOACCESS(old_esp);
+         make_aligned_word_NOACCESS(old_esp+4);
+         return;
+      }
+
+      if (delta == -16) {
+         PROF_EVENT(110);
          make_aligned_word_WRITABLE(new_esp);
          make_aligned_word_WRITABLE(new_esp+4);
          make_aligned_word_WRITABLE(new_esp+8);
+         make_aligned_word_WRITABLE(new_esp+12);
          return;
       }
 
-      if (delta == 8) {
-         PROF_EVENT(106);
+      if (delta == 20) {
+         PROF_EVENT(111);
          make_aligned_word_NOACCESS(old_esp);
          make_aligned_word_NOACCESS(old_esp+4);
+         make_aligned_word_NOACCESS(old_esp+8);
+         make_aligned_word_NOACCESS(old_esp+12);
+         make_aligned_word_NOACCESS(old_esp+16);
          return;
       }
 
-      if (delta == -8) {
-         PROF_EVENT(107);
+      if (delta == -20) {
+         PROF_EVENT(112);
          make_aligned_word_WRITABLE(new_esp);
          make_aligned_word_WRITABLE(new_esp+4);
+         make_aligned_word_WRITABLE(new_esp+8);
+         make_aligned_word_WRITABLE(new_esp+12);
+         make_aligned_word_WRITABLE(new_esp+16);
          return;
       }
+
+      if (delta == 24) {
+         PROF_EVENT(113);
+         make_aligned_word_NOACCESS(old_esp);
+         make_aligned_word_NOACCESS(old_esp+4);
+         make_aligned_word_NOACCESS(old_esp+8);
+         make_aligned_word_NOACCESS(old_esp+12);
+         make_aligned_word_NOACCESS(old_esp+16);
+         make_aligned_word_NOACCESS(old_esp+20);
+         return;
+      }
+
+      if (delta == -24) {
+         PROF_EVENT(114);
+         make_aligned_word_WRITABLE(new_esp);
+         make_aligned_word_WRITABLE(new_esp+4);
+         make_aligned_word_WRITABLE(new_esp+8);
+         make_aligned_word_WRITABLE(new_esp+12);
+         make_aligned_word_WRITABLE(new_esp+16);
+         make_aligned_word_WRITABLE(new_esp+20);
+         return;
+      }
+
    }
 
 #  endif
@@ -1431,23 +1501,23 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
    UInt old_esp = VG_(baseBlock)[VGOFF_(m_esp)];
    UInt new_esp = (UInt)new_espA;
    Int  delta   = ((Int)new_esp) - ((Int)old_esp);
-
-   PROF_EVENT(110);
+   //   VG_(printf)("%d ", delta);
+   PROF_EVENT(120);
    if (-(VG_HUGE_DELTA) < delta && delta < VG_HUGE_DELTA) {
       /* "Ordinary" stack change. */
       if (new_esp < old_esp) {
          /* Moving down; the stack is growing. */
-         PROF_EVENT(111);
+         PROF_EVENT(121);
          VGM_(make_writable) ( new_esp, old_esp - new_esp );
          return;
       }
       if (new_esp > old_esp) {
          /* Moving up; the stack is shrinking. */
-         PROF_EVENT(112);
+         PROF_EVENT(122);
          VGM_(make_noaccess) ( old_esp, new_esp - old_esp );
          return;
       }
-      PROF_EVENT(113);
+      PROF_EVENT(123);
       return; /* when old_esp == new_esp */
    }
 
@@ -1470,7 +1540,7 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
      Addr valid_up_to     = get_page_base(new_esp) + VKI_BYTES_PER_PAGE
                             + 0 * VKI_BYTES_PER_PAGE;
      ThreadState* tst     = VG_(get_current_thread_state)();
-     PROF_EVENT(114);
+     PROF_EVENT(124);
      if (VG_(clo_verbosity) > 1)
         VG_(message)(Vg_UserMsg, "Warning: client switching stacks?  "
                                  "%%esp: %p --> %p",
index 4be838c19303ec88a7eb3dde34f04b7e963323b9..607926ed652f95670e675e2c7f2df3cc81b7b735 100644 (file)
@@ -3704,10 +3704,42 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
    case 0x59: /* POP eCX */
    case 0x5A: /* POP eDX */
    case 0x5B: /* POP eBX */
-   case 0x5C: /* POP eSP */
    case 0x5D: /* POP eBP */
    case 0x5E: /* POP eSI */
    case 0x5F: /* POP eDI */
+    { Int   n_pops;
+      Addr  eipS, eipE;
+      UChar ch;
+      if (sz != 4) goto normal_pop_case;
+      /* eip points at first pop insn + 1.  Make eipS and eipE
+         bracket the sequence. */
+      eipE = eipS = eip - 1;
+      while (True) { 
+         ch = getUChar(eipE+1);
+         if (ch < 0x58 || ch > 0x5F || ch == 0x5C) break;
+         eipE++;
+      }
+      n_pops = eipE - eipS + 1;
+      if (0 && n_pops > 1) VG_(printf)("%d pops\n", n_pops);
+      t1 = newTemp(cb); t3 = newTemp(cb);
+      uInstr2(cb, GET,    4, ArchReg, R_ESP,    TempReg, t1);
+      for (; eipS <= eipE; eipS++) {
+         ch = getUChar(eipS);
+        uInstr2(cb, LOAD, 4, TempReg, t1, TempReg, t3);
+         uInstr2(cb, PUT,  4, TempReg, t3, ArchReg, ch-0x58);
+         uInstr2(cb, ADD,  4, Literal, 0,        TempReg, t1);
+         uLiteral(cb, 4);
+         SMC_IF_ALL(cb);
+         if (dis) 
+            VG_(printf)("popl %s\n", nameIReg(4,ch-0x58));
+      }
+      uInstr2(cb, PUT,    4, TempReg, t1,       ArchReg, R_ESP);
+      eip = eipE + 1;
+      break;
+    }
+
+   case 0x5C: /* POP eSP */
+   normal_pop_case:
       t1 = newTemp(cb); t2 = newTemp(cb);
       uInstr2(cb, GET,    4, ArchReg, R_ESP,    TempReg, t2);
       uInstr2(cb, LOAD,  sz, TempReg, t2,       TempReg, t1);
@@ -3780,11 +3812,46 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
    case 0x50: /* PUSH eAX */
    case 0x51: /* PUSH eCX */
    case 0x52: /* PUSH eDX */
-   case 0x54: /* PUSH eSP */
    case 0x53: /* PUSH eBX */
    case 0x55: /* PUSH eBP */
    case 0x56: /* PUSH eSI */
    case 0x57: /* PUSH eDI */
+    { Int   n_pushes;
+      Addr  eipS, eipE;
+      UChar ch;
+      if (sz != 4) goto normal_push_case;
+      /* eip points at first push insn + 1.  Make eipS and eipE
+         bracket the sequence. */
+      eipE = eipS = eip - 1;
+      while (True) { 
+         ch = getUChar(eipE+1);
+         if (ch < 0x50 || ch > 0x57 || ch == 0x54) break;
+         eipE++;
+      }
+      n_pushes = eipE - eipS + 1;
+      if (0 && n_pushes > 1) VG_(printf)("%d pushes\n", n_pushes);
+      t1 = newTemp(cb); t2 = newTemp(cb); t3 = newTemp(cb);
+      uInstr2(cb, GET,    4, ArchReg, R_ESP,    TempReg, t1);
+      uInstr2(cb, MOV,    4, TempReg, t1,       TempReg, t2);
+      uInstr2(cb, SUB,    4, Literal, 0,        TempReg, t2);
+      uLiteral(cb, 4 * n_pushes);
+      uInstr2(cb, PUT,    4, TempReg, t2,       ArchReg, R_ESP);
+      for (; eipS <= eipE; eipS++) {
+         ch = getUChar(eipS);
+         uInstr2(cb, SUB,    4, Literal, 0,        TempReg, t1);
+         uLiteral(cb, 4);
+         uInstr2(cb, GET, 4, ArchReg, ch-0x50, TempReg, t3);
+        uInstr2(cb, STORE, 4, TempReg, t3, TempReg, t1);
+         SMC_IF_ALL(cb);
+         if (dis) 
+            VG_(printf)("pushl %s\n", nameIReg(4,ch-0x50));
+      }
+      eip = eipE + 1;
+      break;
+    }
+
+   case 0x54: /* PUSH eSP */
+   normal_push_case:
       /* This is the Right Way, in that the value to be pushed is
          established before %esp is changed, so that pushl %esp
          correctly pushes the old value. */
index 59d183b48a4fa327b9660e640a367a8072d8baf3..a6a2c5d92962bfd740a1b8c07d49ceb52db4108d 100644 (file)
@@ -99,7 +99,7 @@
 
 #ifdef VG_PROFILE_MEMORY
 
-#define N_PROF_EVENTS 120
+#define N_PROF_EVENTS 150
 
 static UInt event_ctr[N_PROF_EVENTS];
 
@@ -204,16 +204,23 @@ static void init_prof_mem ( void ) { }
    101  handle_esp_assignment
    102  handle_esp_assignment(-4)
    103  handle_esp_assignment(+4)
-   104  handle_esp_assignment(+16)
-   105  handle_esp_assignment(-12)
-   106  handle_esp_assignment(+8)
-   107  handle_esp_assignment(-8)
-
-   110  vg_handle_esp_assignment_SLOWLY
-   111  vg_handle_esp_assignment_SLOWLY(normal; move down)
-   112  vg_handle_esp_assignment_SLOWLY(normal; move up)
-   113  vg_handle_esp_assignment_SLOWLY(normal)
-   114  vg_handle_esp_assignment_SLOWLY(>= HUGE_DELTA)
+   104  handle_esp_assignment(-12)
+   105  handle_esp_assignment(-8)
+   106  handle_esp_assignment(+16)
+   107  handle_esp_assignment(+12)
+   108  handle_esp_assignment(0)
+   109  handle_esp_assignment(+8)
+   110  handle_esp_assignment(-16)
+   111  handle_esp_assignment(+20)
+   112  handle_esp_assignment(-20)
+   113  handle_esp_assignment(+24)
+   114  handle_esp_assignment(-24)
+
+   120  vg_handle_esp_assignment_SLOWLY
+   121  vg_handle_esp_assignment_SLOWLY(normal; move down)
+   122  vg_handle_esp_assignment_SLOWLY(normal; move up)
+   123  vg_handle_esp_assignment_SLOWLY(normal)
+   124  vg_handle_esp_assignment_SLOWLY(>= HUGE_DELTA)
 */
 
 /*------------------------------------------------------------*/
@@ -712,7 +719,6 @@ static __inline__ UInt shiftRight16 ( UInt x )
    Under all other circumstances, it defers to the relevant _SLOWLY
    function, which can handle all situations.
 */
-
 UInt VG_(helperc_LOADV4) ( Addr a )
 {
 #  ifdef VG_DEBUG_MEMORY
@@ -1384,9 +1390,23 @@ void VGM_(handle_esp_assignment) ( Addr new_espA )
          return;
       }
 
-      if (delta == 16) {
-         /* Also surprisingly common. */
+      if (delta == -12) {
          PROF_EVENT(104);
+         make_aligned_word_WRITABLE(new_esp);
+         make_aligned_word_WRITABLE(new_esp+4);
+         make_aligned_word_WRITABLE(new_esp+8);
+         return;
+      }
+
+      if (delta == -8) {
+         PROF_EVENT(105);
+         make_aligned_word_WRITABLE(new_esp);
+         make_aligned_word_WRITABLE(new_esp+4);
+         return;
+      }
+
+      if (delta == 16) {
+         PROF_EVENT(106);
          make_aligned_word_NOACCESS(old_esp);
          make_aligned_word_NOACCESS(old_esp+4);
          make_aligned_word_NOACCESS(old_esp+8);
@@ -1394,27 +1414,77 @@ void VGM_(handle_esp_assignment) ( Addr new_espA )
          return;
       }
 
-      if (delta == -12) {
-         PROF_EVENT(105);
+      if (delta == 12) {
+         PROF_EVENT(107);
+         make_aligned_word_NOACCESS(old_esp);
+         make_aligned_word_NOACCESS(old_esp+4);
+         make_aligned_word_NOACCESS(old_esp+8);
+         return;
+      }
+
+      if (delta == 0) {
+         PROF_EVENT(108);
+         return;
+      }
+
+      if (delta == 8) {
+         PROF_EVENT(109);
+         make_aligned_word_NOACCESS(old_esp);
+         make_aligned_word_NOACCESS(old_esp+4);
+         return;
+      }
+
+      if (delta == -16) {
+         PROF_EVENT(110);
          make_aligned_word_WRITABLE(new_esp);
          make_aligned_word_WRITABLE(new_esp+4);
          make_aligned_word_WRITABLE(new_esp+8);
+         make_aligned_word_WRITABLE(new_esp+12);
          return;
       }
 
-      if (delta == 8) {
-         PROF_EVENT(106);
+      if (delta == 20) {
+         PROF_EVENT(111);
          make_aligned_word_NOACCESS(old_esp);
          make_aligned_word_NOACCESS(old_esp+4);
+         make_aligned_word_NOACCESS(old_esp+8);
+         make_aligned_word_NOACCESS(old_esp+12);
+         make_aligned_word_NOACCESS(old_esp+16);
          return;
       }
 
-      if (delta == -8) {
-         PROF_EVENT(107);
+      if (delta == -20) {
+         PROF_EVENT(112);
          make_aligned_word_WRITABLE(new_esp);
          make_aligned_word_WRITABLE(new_esp+4);
+         make_aligned_word_WRITABLE(new_esp+8);
+         make_aligned_word_WRITABLE(new_esp+12);
+         make_aligned_word_WRITABLE(new_esp+16);
          return;
       }
+
+      if (delta == 24) {
+         PROF_EVENT(113);
+         make_aligned_word_NOACCESS(old_esp);
+         make_aligned_word_NOACCESS(old_esp+4);
+         make_aligned_word_NOACCESS(old_esp+8);
+         make_aligned_word_NOACCESS(old_esp+12);
+         make_aligned_word_NOACCESS(old_esp+16);
+         make_aligned_word_NOACCESS(old_esp+20);
+         return;
+      }
+
+      if (delta == -24) {
+         PROF_EVENT(114);
+         make_aligned_word_WRITABLE(new_esp);
+         make_aligned_word_WRITABLE(new_esp+4);
+         make_aligned_word_WRITABLE(new_esp+8);
+         make_aligned_word_WRITABLE(new_esp+12);
+         make_aligned_word_WRITABLE(new_esp+16);
+         make_aligned_word_WRITABLE(new_esp+20);
+         return;
+      }
+
    }
 
 #  endif
@@ -1431,23 +1501,23 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
    UInt old_esp = VG_(baseBlock)[VGOFF_(m_esp)];
    UInt new_esp = (UInt)new_espA;
    Int  delta   = ((Int)new_esp) - ((Int)old_esp);
-
-   PROF_EVENT(110);
+   //   VG_(printf)("%d ", delta);
+   PROF_EVENT(120);
    if (-(VG_HUGE_DELTA) < delta && delta < VG_HUGE_DELTA) {
       /* "Ordinary" stack change. */
       if (new_esp < old_esp) {
          /* Moving down; the stack is growing. */
-         PROF_EVENT(111);
+         PROF_EVENT(121);
          VGM_(make_writable) ( new_esp, old_esp - new_esp );
          return;
       }
       if (new_esp > old_esp) {
          /* Moving up; the stack is shrinking. */
-         PROF_EVENT(112);
+         PROF_EVENT(122);
          VGM_(make_noaccess) ( old_esp, new_esp - old_esp );
          return;
       }
-      PROF_EVENT(113);
+      PROF_EVENT(123);
       return; /* when old_esp == new_esp */
    }
 
@@ -1470,7 +1540,7 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
      Addr valid_up_to     = get_page_base(new_esp) + VKI_BYTES_PER_PAGE
                             + 0 * VKI_BYTES_PER_PAGE;
      ThreadState* tst     = VG_(get_current_thread_state)();
-     PROF_EVENT(114);
+     PROF_EVENT(124);
      if (VG_(clo_verbosity) > 1)
         VG_(message)(Vg_UserMsg, "Warning: client switching stacks?  "
                                  "%%esp: %p --> %p",
index 4be838c19303ec88a7eb3dde34f04b7e963323b9..607926ed652f95670e675e2c7f2df3cc81b7b735 100644 (file)
@@ -3704,10 +3704,42 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
    case 0x59: /* POP eCX */
    case 0x5A: /* POP eDX */
    case 0x5B: /* POP eBX */
-   case 0x5C: /* POP eSP */
    case 0x5D: /* POP eBP */
    case 0x5E: /* POP eSI */
    case 0x5F: /* POP eDI */
+    { Int   n_pops;
+      Addr  eipS, eipE;
+      UChar ch;
+      if (sz != 4) goto normal_pop_case;
+      /* eip points at first pop insn + 1.  Make eipS and eipE
+         bracket the sequence. */
+      eipE = eipS = eip - 1;
+      while (True) { 
+         ch = getUChar(eipE+1);
+         if (ch < 0x58 || ch > 0x5F || ch == 0x5C) break;
+         eipE++;
+      }
+      n_pops = eipE - eipS + 1;
+      if (0 && n_pops > 1) VG_(printf)("%d pops\n", n_pops);
+      t1 = newTemp(cb); t3 = newTemp(cb);
+      uInstr2(cb, GET,    4, ArchReg, R_ESP,    TempReg, t1);
+      for (; eipS <= eipE; eipS++) {
+         ch = getUChar(eipS);
+        uInstr2(cb, LOAD, 4, TempReg, t1, TempReg, t3);
+         uInstr2(cb, PUT,  4, TempReg, t3, ArchReg, ch-0x58);
+         uInstr2(cb, ADD,  4, Literal, 0,        TempReg, t1);
+         uLiteral(cb, 4);
+         SMC_IF_ALL(cb);
+         if (dis) 
+            VG_(printf)("popl %s\n", nameIReg(4,ch-0x58));
+      }
+      uInstr2(cb, PUT,    4, TempReg, t1,       ArchReg, R_ESP);
+      eip = eipE + 1;
+      break;
+    }
+
+   case 0x5C: /* POP eSP */
+   normal_pop_case:
       t1 = newTemp(cb); t2 = newTemp(cb);
       uInstr2(cb, GET,    4, ArchReg, R_ESP,    TempReg, t2);
       uInstr2(cb, LOAD,  sz, TempReg, t2,       TempReg, t1);
@@ -3780,11 +3812,46 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
    case 0x50: /* PUSH eAX */
    case 0x51: /* PUSH eCX */
    case 0x52: /* PUSH eDX */
-   case 0x54: /* PUSH eSP */
    case 0x53: /* PUSH eBX */
    case 0x55: /* PUSH eBP */
    case 0x56: /* PUSH eSI */
    case 0x57: /* PUSH eDI */
+    { Int   n_pushes;
+      Addr  eipS, eipE;
+      UChar ch;
+      if (sz != 4) goto normal_push_case;
+      /* eip points at first push insn + 1.  Make eipS and eipE
+         bracket the sequence. */
+      eipE = eipS = eip - 1;
+      while (True) { 
+         ch = getUChar(eipE+1);
+         if (ch < 0x50 || ch > 0x57 || ch == 0x54) break;
+         eipE++;
+      }
+      n_pushes = eipE - eipS + 1;
+      if (0 && n_pushes > 1) VG_(printf)("%d pushes\n", n_pushes);
+      t1 = newTemp(cb); t2 = newTemp(cb); t3 = newTemp(cb);
+      uInstr2(cb, GET,    4, ArchReg, R_ESP,    TempReg, t1);
+      uInstr2(cb, MOV,    4, TempReg, t1,       TempReg, t2);
+      uInstr2(cb, SUB,    4, Literal, 0,        TempReg, t2);
+      uLiteral(cb, 4 * n_pushes);
+      uInstr2(cb, PUT,    4, TempReg, t2,       ArchReg, R_ESP);
+      for (; eipS <= eipE; eipS++) {
+         ch = getUChar(eipS);
+         uInstr2(cb, SUB,    4, Literal, 0,        TempReg, t1);
+         uLiteral(cb, 4);
+         uInstr2(cb, GET, 4, ArchReg, ch-0x50, TempReg, t3);
+        uInstr2(cb, STORE, 4, TempReg, t3, TempReg, t1);
+         SMC_IF_ALL(cb);
+         if (dis) 
+            VG_(printf)("pushl %s\n", nameIReg(4,ch-0x50));
+      }
+      eip = eipE + 1;
+      break;
+    }
+
+   case 0x54: /* PUSH eSP */
+   normal_push_case:
       /* This is the Right Way, in that the value to be pushed is
          established before %esp is changed, so that pushl %esp
          correctly pushes the old value. */