From: Julian Seward Date: Sat, 30 Nov 2002 15:01:01 +0000 (+0000) Subject: Merge patch from JeremyF: X-Git-Tag: svn/VALGRIND_1_9_4~108 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bf0d5036dac0df15d1364a025c2b16b6644449e6;p=thirdparty%2Fvalgrind.git Merge patch from JeremyF: 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 --- diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c index 11843eec1a..645988cd27 100644 --- a/coregrind/vg_from_ucode.c +++ b/coregrind/vg_from_ucode.c @@ -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 // 5 + $01 // 1 1: mov $0x4000d042,%eax call 0x40050f9a */ - 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 diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 00fa4ba923..fba0051b59 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -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); /* --------------------------------------------------------------------- diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index 4fed5802ec..2c524fb2f6 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -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= 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")) diff --git a/include/vg_skin.h b/include/vg_skin.h index e7481110a4..e56c8ebf21 100644 --- a/include/vg_skin.h +++ b/include/vg_skin.h @@ -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