Skip to content

Commit 380625b

Browse files
committed
qemu/target/avr: add support for block and insn hooks.
Signed-off-by: Glenn Baker <[email protected]>
1 parent 6e7f40c commit 380625b

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

qemu/target/avr/translate.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2988,11 +2988,35 @@ static void translate(DisasContext *ctx)
29882988
return;
29892989
}
29902990

2991+
// Unicorn: trace this instruction on request
2992+
bool insn_hook = false;
2993+
TCGOp *insn_prev_op = NULL;
2994+
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_CODE, insn_pc*2)) {
2995+
2996+
// sync PC in advance
2997+
tcg_gen_movi_tl(cpu_pc, insn_pc);
2998+
2999+
// save the last operand
3000+
insn_prev_op = tcg_last_op(tcg_ctx);
3001+
insn_hook = true;
3002+
gen_uc_tracecode(tcg_ctx, 0xf1, UC_HOOK_CODE_IDX, uc, insn_pc*2);
3003+
3004+
// the callback might want to stop emulation immediately
3005+
check_exit_request(tcg_ctx);
3006+
}
3007+
29913008
uint32_t opcode = next_word(ctx);
29923009
if (!decode_insn(ctx, opcode)) {
29933010
gen_helper_unsupported(cpu_env);
29943011
ctx->bstate = DISAS_NORETURN;
29953012
}
3013+
3014+
if (insn_hook) {
3015+
// Unicorn: patch the callback to have the proper instruction size.
3016+
TCGOp *const tcg_op = insn_prev_op ?
3017+
QTAILQ_NEXT(insn_prev_op, link) : QTAILQ_FIRST(&tcg_ctx->ops);
3018+
tcg_op->args[1] = (ctx->npc - insn_pc)*2;
3019+
}
29963020
}
29973021

29983022
/* Standardize the cpu_skip condition to NE. */
@@ -3056,7 +3080,9 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
30563080
target_ulong pc_start = tb->pc / 2;
30573081
int num_insns = 0;
30583082

3083+
INIT_UC_CONTEXT_FROM_DISAS(&ctx);
30593084
INIT_TCG_CONTEXT_AND_CPU_ENV_FROM_DISAS(&ctx);
3085+
30603086
if (tb->flags & TB_FLAGS_FULL_ACCESS) {
30613087
/*
30623088
* This flag is set by ST/LD instruction we will regenerate it ONLY
@@ -3068,6 +3094,17 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
30683094
max_insns = 1;
30693095
}
30703096

3097+
// Unicorn: trace this block on request
3098+
bool block_hook = false;
3099+
TCGOp *block_prev_op = NULL;
3100+
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_BLOCK, tb->pc)) {
3101+
3102+
// save the last operand
3103+
block_prev_op = tcg_last_op(tcg_ctx);
3104+
block_hook = true;
3105+
gen_uc_tracecode(tcg_ctx, 0xf8, UC_HOOK_BLOCK_IDX, uc, tb->pc);
3106+
}
3107+
30713108
gen_tb_start(tb);
30723109

30733110
ctx.npc = pc_start;
@@ -3188,6 +3225,15 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31883225
tb->size = (ctx.npc - pc_start) * 2;
31893226
tb->icount = num_insns;
31903227

3228+
hooked_regions_check(uc, tb->pc, tb->size);
3229+
3230+
if (block_hook) {
3231+
// Unicorn: patch the callback to have the proper block size.
3232+
TCGOp *const tcg_op = block_prev_op ?
3233+
QTAILQ_NEXT(block_prev_op, link) : QTAILQ_FIRST(&tcg_ctx->ops);
3234+
tcg_op->args[1] = (ctx.npc - pc_start)*2;
3235+
}
3236+
31913237
#ifdef DEBUG_DISAS
31923238
#if 0
31933239
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)

0 commit comments

Comments
 (0)