}
+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
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
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
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. */
" --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"
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"))
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)
#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