@@ -32,6 +32,32 @@
#define GEN_HELPER 1
#include "helper.h"
+#if defined(CONFIG_INSTRUMENT)
+static inline void
+mem_exchange (void * tmp, void * start1, size_t size1,
+ void * start2, size_t size2)
+{
+ memcpy(tmp , start2, size2);
+ memcpy(tmp+size2, start1, size1);
+ memcpy(start1 , tmp , size1+size2);
+}
+#endif
+
+
+/* tracking of register usage */
+#if defined(CONFIG_INSTRUMENT)
+struct DisasContext;
+/* Have current context always accessible */
+struct DisasContext * instr_disas = NULL;
+#endif
+
+#define INSTR_REGS_SET_GP(s, r) INSTR_REGS_SET(instr_disas->instr_regs_ ##s, r)
+/* TODO: access to env->regs in helper functions */
+/* TODO: not tracking register sets for: eflags, segments, floating point,
+ * crX, ...
+ */
+
+
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
@@ -116,6 +142,11 @@ typedef struct DisasContext {
int cpuid_ext_features;
int cpuid_ext2_features;
int cpuid_ext3_features;
+#if defined(CONFIG_INSTRUMENT)
+ /* temporal vars for FETCH instrumentation */
+ instr_regs_t instr_regs_used;
+ instr_regs_t instr_regs_defined;
+#endif
} DisasContext;
static void gen_eob(DisasContext *s);
@@ -281,9 +312,13 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
tmp = tcg_temp_new();
tcg_gen_ext8u_tl(tmp, t0);
if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xff);
tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
} else {
+ INSTR_REGS_SET_GP(used, reg - 4);
+ INSTR_REGS_SET_GP(defined, reg - 4);
tcg_gen_shli_tl(tmp, tmp, 8);
tcg_gen_andi_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], ~0xff00);
tcg_gen_or_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], tmp);
@@ -293,6 +328,8 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
case OT_WORD:
tmp = tcg_temp_new();
tcg_gen_ext16u_tl(tmp, t0);
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
tcg_temp_free(tmp);
@@ -301,10 +338,12 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
case OT_LONG:
/* For x86_64, this sets the higher half of register to zero.
For i386, this is equivalent to a mov. */
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_ext32u_tl(cpu_regs[reg], t0);
break;
#ifdef TARGET_X86_64
case OT_QUAD:
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_mov_tl(cpu_regs[reg], t0);
break;
#endif
@@ -329,6 +368,8 @@ static inline void gen_op_mov_reg_A0(int size, int reg)
case 0:
tmp = tcg_temp_new();
tcg_gen_ext16u_tl(tmp, cpu_A0);
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
tcg_temp_free(tmp);
@@ -337,10 +378,12 @@ static inline void gen_op_mov_reg_A0(int size, int reg)
case 1:
/* For x86_64, this sets the higher half of register to zero.
For i386, this is equivalent to a mov. */
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
break;
#ifdef TARGET_X86_64
case 2:
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
break;
#endif
@@ -354,12 +397,14 @@ static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
goto std_case;
} else {
+ INSTR_REGS_SET_GP(used, reg - 4);
tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
tcg_gen_ext8u_tl(t0, t0);
}
break;
default:
std_case:
+ INSTR_REGS_SET_GP(used, reg);
tcg_gen_mov_tl(t0, cpu_regs[reg]);
break;
}
@@ -372,6 +417,7 @@ static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
static inline void gen_op_movl_A0_reg(int reg)
{
+ INSTR_REGS_SET_GP(used, reg);
tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
}
@@ -414,12 +460,16 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
{
switch(size) {
case 0:
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
break;
case 1:
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
/* For x86_64, this sets the higher half of register to zero.
For i386, this is equivalent to a nop. */
@@ -428,6 +478,8 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
break;
#ifdef TARGET_X86_64
case 2:
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
break;
#endif
@@ -438,12 +490,16 @@ static inline void gen_op_add_reg_T0(int size, int reg)
{
switch(size) {
case 0:
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
break;
case 1:
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
/* For x86_64, this sets the higher half of register to zero.
For i386, this is equivalent to a nop. */
@@ -452,6 +508,8 @@ static inline void gen_op_add_reg_T0(int size, int reg)
break;
#ifdef TARGET_X86_64
case 2:
+ INSTR_REGS_SET_GP(used, reg);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
break;
#endif
@@ -465,6 +523,7 @@ static inline void gen_op_set_cc_op(int32_t val)
static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
{
+ INSTR_REGS_SET_GP(used, reg);
tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
if (shift != 0)
tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
@@ -502,11 +561,13 @@ static inline void gen_op_addq_A0_seg(int reg)
static inline void gen_op_movq_A0_reg(int reg)
{
+ INSTR_REGS_SET_GP(used, reg);
tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
}
static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
{
+ INSTR_REGS_SET_GP(used, reg);
tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
if (shift != 0)
tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
@@ -707,6 +768,7 @@ static void gen_exts(int ot, TCGv reg)
static inline void gen_op_jnz_ecx(int size, int label1)
{
+ INSTR_REGS_SET_GP(used, R_ECX);
tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
gen_extu(size + 1, cpu_tmp0);
tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
@@ -714,6 +776,7 @@ static inline void gen_op_jnz_ecx(int size, int label1)
static inline void gen_op_jz_ecx(int size, int label1)
{
+ INSTR_REGS_SET_GP(used, R_ECX);
tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
gen_extu(size + 1, cpu_tmp0);
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
@@ -4090,6 +4153,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
target_ulong next_eip, tval;
int rex_w, rex_r;
+#if defined(CONFIG_INSTRUMENT)
+ uint16_t * instr_gen_opc_ptr = gen_opc_ptr;
+ TCGArg * instr_gen_opparam_ptr = gen_opparam_ptr;
+#endif
+
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
tcg_gen_debug_insn_start(pc_start);
s->pc = pc_start;
@@ -4105,6 +4173,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
x86_64_hregs = 0;
#endif
s->rip_offset = 0; /* for relative ip address */
+#if defined(CONFIG_INSTRUMENT)
+ s->instr_regs_used = 0;
+ s->instr_regs_defined = 0;
+#endif
#if defined(CONFIG_BACKDOOR)
if (ldub_code(s->pc) == 0x0f && ldub_code(s->pc + 1) == 0x04) {
@@ -4118,6 +4190,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
break;
case 0x01: /* i8 v */
cmd = tcg_const_i32(ldub_code(s->pc + 3));
+ INSTR_REGS_SET_GP(used, R_EAX);
gen_helper_backdoor_i8_v(cmd, cpu_regs[R_EAX]);
break;
default:
@@ -4901,6 +4974,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
rm = 0; /* avoid warning */
}
label1 = gen_new_label();
+ INSTR_REGS_SET_GP(used, R_EAX);
tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0);
gen_extu(ot, t2);
tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
@@ -5476,6 +5550,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
val = ldub_code(s->pc++);
tcg_gen_movi_tl(cpu_T3, val);
} else {
+ INSTR_REGS_SET_GP(used, R_ECX);
tcg_gen_mov_tl(cpu_T3, cpu_regs[R_ECX]);
}
gen_shiftd_rm_T1_T3(s, ot, opreg, op);
@@ -6386,6 +6461,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
/* XXX: specific Intel behaviour ? */
l1 = gen_new_label();
gen_jcc1(s, s->cc_op, b ^ 1, l1);
+ INSTR_REGS_SET_GP(defined, reg);
tcg_gen_mov_tl(cpu_regs[reg], t0);
gen_set_label(l1);
tcg_gen_ext32u_tl(cpu_regs[reg], cpu_regs[reg]);
@@ -7666,6 +7742,36 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
backdoor_done:
#endif
+#if defined(CONFIG_INSTRUMENT)
+ {
+ uint16_t * old_gen_opc_ptr = gen_opc_ptr;
+ TCGArg * old_gen_opparam_ptr = gen_opparam_ptr;
+
+ INSTR_GEN_FETCH(TUL, pc_start,
+ I32, s->pc - pc_start,
+ REGS, s->instr_regs_used,
+ REGS, s->instr_regs_defined);
+
+ /* Move TCG code generated by instrumentation callback */
+
+ if (old_gen_opc_ptr != gen_opc_ptr) {
+ typeof(*gen_opc_ptr) tmp[OPC_BUF_SIZE];
+ mem_exchange(tmp, instr_gen_opc_ptr,
+ (old_gen_opc_ptr - instr_gen_opc_ptr) * sizeof(*gen_opc_ptr),
+ old_gen_opc_ptr,
+ (gen_opc_ptr - old_gen_opc_ptr) * sizeof(*gen_opc_ptr));
+ }
+
+ if (old_gen_opparam_ptr != gen_opparam_ptr) {
+ typeof(*gen_opparam_ptr) tmp[OPPARAM_BUF_SIZE];
+ mem_exchange(tmp, instr_gen_opparam_ptr,
+ (old_gen_opparam_ptr - instr_gen_opparam_ptr) * sizeof(*gen_opparam_ptr),
+ old_gen_opparam_ptr,
+ (gen_opparam_ptr - old_gen_opparam_ptr) * sizeof(*gen_opparam_ptr));
+ }
+ }
+#endif
+
/* lock generation */
if (s->prefix & PREFIX_LOCK)
gen_helper_unlock();
@@ -7812,6 +7918,9 @@ static inline void gen_intermediate_code_internal(CPUState *env,
|| (flags & HF_SOFTMMU_MASK)
#endif
);
+#if defined(CONFIG_INSTRUMENT)
+ instr_disas = dc;
+#endif
#if 0
/* check addseg logic */
if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
@@ -7930,6 +8039,10 @@ static inline void gen_intermediate_code_internal(CPUState *env,
tb->size = pc_ptr - pc_start;
tb->icount = num_insns;
}
+
+#if defined(CONFIG_INSTRUMENT)
+ instr_disas = NULL;
+#endif
}
void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
Provides an instrumentation point for instruction fetch/decode events. Signed-off-by: LluĂs Vilanova <vilanova@ac.upc.edu> --- target-i386/translate.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 113 insertions(+), 0 deletions(-)