]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Merge patch from JeremyF:
authorJulian Seward <jseward@acm.org>
Sat, 30 Nov 2002 15:01:01 +0000 (15:01 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 30 Nov 2002 15:01:01 +0000 (15:01 +0000)
50-fast-cond

Implement Julian's idea for fast conditional jumps. Rather than fully
restoring the eflags register with an expensive push-popf pair, just
test the flag bits directly out of the base block. Faster, and smaller
code too!

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

coregrind/vg_from_ucode.c
coregrind/vg_include.h
coregrind/vg_main.c
include/vg_skin.h

index 11843eec1a5f4b5eb428ba77d4a9ee944f3ae3f8..645988cd276400d39377bf5b0d2ebfb6172ae409 100644 (file)
@@ -1535,8 +1535,16 @@ static void synth_jmp_lit ( Addr addr, JmpKind jmpkind )
 }
 
 
+static void synth_mov_offregmem_reg ( Int size, Int off, Int areg, Int reg );
+static void synth_nonshiftop_lit_reg ( Bool upd_cc,
+                                       Opcode opcode, Int size, 
+                                       UInt lit, Int reg );
+
 static void synth_jcond_lit ( Condcode cond, Addr addr )
 {
+   UInt mask;
+   Int delta;
+
   /* Do the following:
         get eflags
         jmp short if not cond to xyxyxy
@@ -1550,7 +1558,6 @@ static void synth_jcond_lit ( Condcode cond, Addr addr )
    5 0008 FFE3                  jmp     *%ebx
    6                    xyxyxy:
   */
-   emit_get_eflags();
    if (VG_(clo_chain_bb)) {
       /* When using BB chaining, the jump sequence is:
         jmp short if not cond to xyxyxy
@@ -1562,16 +1569,65 @@ static void synth_jcond_lit ( Condcode cond, Addr addr )
                mov    $0x4000d190,%eax                 // 5
                mov    %eax, VGOFF_(m_eip)(%ebp)        // 3
                call   0x40050f9a <vgPlain_patch_me>    // 5
+               $01                                     // 1
        1:      mov    $0x4000d042,%eax
                call   0x40050f9a <vgPlain_patch_me>
       */
-      VG_(emit_jcondshort_delta) ( invertCondition(cond), 5+3+5 );
+      delta = 5+3+5+1 -1;
    } else
-      VG_(emit_jcondshort_delta) ( invertCondition(cond), 5+1 );
+      delta = 5+1;
+   
+   if (!VG_(clo_fast_jcc)) {
+      /* We're forced to do it the slow way. */
+      emit_get_eflags();
+      cond = invertCondition(cond);
+   } else {
+      switch (cond & ~1) {
+         case CondB:  mask = EFlagC;          goto common;  /* C=1        */
+         case CondZ:  mask = EFlagZ;          goto common;  /* Z=1        */
+         case CondBE: mask = EFlagC | EFlagZ; goto common;  /* C=1 || Z=1 */
+         case CondS:  mask = EFlagS;          goto common;  /* S=1        */
+         case CondP:  mask = EFlagP;          goto common;  /* P=1        */
+         default:
+            /* Too complex .. we have to do it the slow way. */
+            emit_get_eflags();
+            cond = invertCondition(cond);
+            break;
+
+        common:
+            VG_(new_emit)();
+            if ((mask & 0xff) == mask) {
+               VG_(emitB) ( 0xF6 );   /* Grp3 */
+               VG_(emit_amode_offregmem_reg)(
+                  VGOFF_(m_eflags) * 4, R_EBP, 0 /* subcode for TEST */);
+               VG_(emitB) (mask);
+               if (dis)
+                  VG_(printf)("\n\t\ttestb $%x, %d(%%ebp)\n", 
+                              mask, VGOFF_(m_eflags) * 4);
+            } else {
+               VG_(emitB) ( 0xF7 );
+               VG_(emit_amode_offregmem_reg)(
+                  VGOFF_(m_eflags) * 4, R_EBP, 0 /* subcode for TEST */);
+               VG_(emitB) (mask);
+               if (dis)
+                  VG_(printf)("\n\t\ttestx $%x, %d(%%ebp)\n", 
+                              mask, VGOFF_(m_eflags) * 4);
+            }
+
+            if (cond & 1)
+               cond = CondNZ;
+            else
+               cond = CondZ;
+            break;
+      }
+   }
+
+   VG_(emit_jcondshort_delta) ( cond, delta );
    synth_jmp_lit ( addr, JmpBoring );
 }
 
 
+
 static void synth_jmp_ifzero_reg_lit ( Int reg, Addr addr )
 {
    /* 0000 83FF00                cmpl    $0, %edi
index 00fa4ba92387f28bdef042f300693208db0b44d5..fba0051b593cf656f926ea1572fb54ad5e11e9f3 100644 (file)
@@ -246,6 +246,8 @@ extern Char* VG_(clo_weird_hacks);
 extern Bool  VG_(clo_run_libc_freeres);
 /* Use the basic-block chaining optimisation */
 extern Bool VG_(clo_chain_bb);
+/* Generate code for fast conditional jumps (not using pushf/popf) */
+extern Bool VG_(clo_fast_jcc);
 
 
 /* ---------------------------------------------------------------------
index 4fed5802ec8fd419a23f6c1f688299e0c97fd237..2c524fb2f67fad24963368f6cb2aad9b48bfbafc 100644 (file)
@@ -473,6 +473,8 @@ Int    VG_(clo_backtrace_size) = 4;
 Char*  VG_(clo_weird_hacks)    = NULL;
 Bool   VG_(clo_run_libc_freeres) = True;
 Bool   VG_(clo_chain_bb)       = True;
+Bool   VG_(clo_fast_jcc)       = True;
+
 
 /* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
    to behave.  Initially we say False. */
@@ -564,6 +566,7 @@ static void usage ( void )
 "    --optimise=no|yes         improve intermediate code? [yes]\n"
 "    --profile=no|yes          profile? (skin must be built for it) [no]\n"
 "    --chain-bb=no|yes         do basic-block chaining? [yes]\n"
+"    --fast-jcc=no|yes         experimental fast conditional jumps [yes]\n"
 "    --trace-codegen=<XXXXX>   show generated code? (X = 0|1) [00000]\n"
 "    --trace-syscalls=no|yes   show all system calls? [no]\n"
 "    --trace-signals=no|yes    show signal handling details? [no]\n"
@@ -844,6 +847,11 @@ static void process_cmd_line_options ( void )
       else if (STREQ(argv[i], "--chain-bb=no"))
         VG_(clo_chain_bb) = False;
 
+      else if (STREQ(argv[i], "--fast-jcc=yes"))
+        VG_(clo_fast_jcc) = True;
+      else if (STREQ(argv[i], "--fast-jcc=no"))
+        VG_(clo_fast_jcc) = False;
+
       else if (STREQ(argv[i], "--single-step=yes"))
          VG_(clo_single_step) = True;
       else if (STREQ(argv[i], "--single-step=no"))
index e7481110a4d5a56e7bf9714b197dca622276227a..e56c8ebf21d3485df7a00c63aec141cee6110bae 100644 (file)
@@ -609,7 +609,10 @@ typedef
       76543210
        DOSZACP
    and bit 7 must always be zero since it is unused.
-*/
+
+   Note: these Flag? values are **not** the positions in the actual
+   %eflags register.  */
+
 typedef UChar FlagSet;
 
 #define FlagD (1<<6)
@@ -634,6 +637,14 @@ typedef UChar FlagSet;
 #define FlagsEmpty  (FlagSet)0
 
 
+/* flag positions in eflags */
+#define EFlagC  (1 <<  0)       /* carry */
+#define EFlagP  (1 <<  2)       /* parity */
+#define EFlagZ  (1 <<  6)       /* zero */
+#define EFlagS  (1 <<  7)       /* sign */
+#define EFlagO  (1 << 11)       /* overflow */
+
+
 /* Liveness of general purpose registers, useful for code generation.
    Reg rank order 0..N-1 corresponds to bits 0..N-1, ie. first
    reg's liveness in bit 0, last reg's in bit N-1.  Note that