diff options
Diffstat (limited to 'accel/tcg')
-rw-r--r-- | accel/tcg/plugin-gen.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index 2cd0e36..14b6603 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -132,6 +132,51 @@ static TCGv_ptr gen_plugin_u64_ptr(qemu_plugin_u64 entry) return ptr; } +static TCGCond plugin_cond_to_tcgcond(enum qemu_plugin_cond cond) +{ + switch (cond) { + case QEMU_PLUGIN_COND_EQ: + return TCG_COND_EQ; + case QEMU_PLUGIN_COND_NE: + return TCG_COND_NE; + case QEMU_PLUGIN_COND_LT: + return TCG_COND_LTU; + case QEMU_PLUGIN_COND_LE: + return TCG_COND_LEU; + case QEMU_PLUGIN_COND_GT: + return TCG_COND_GTU; + case QEMU_PLUGIN_COND_GE: + return TCG_COND_GEU; + default: + /* ALWAYS and NEVER conditions should never reach */ + g_assert_not_reached(); + } +} + +static void gen_udata_cond_cb(struct qemu_plugin_dyn_cb *cb) +{ + TCGv_ptr ptr = gen_plugin_u64_ptr(cb->cond.entry); + TCGv_i32 cpu_index = tcg_temp_ebb_new_i32(); + TCGv_i64 val = tcg_temp_ebb_new_i64(); + TCGLabel *after_cb = gen_new_label(); + + /* Condition should be negated, as calling the cb is the "else" path */ + TCGCond cond = tcg_invert_cond(plugin_cond_to_tcgcond(cb->cond.cond)); + + tcg_gen_ld_i64(val, ptr, 0); + tcg_gen_brcondi_i64(cond, val, cb->cond.imm, after_cb); + tcg_gen_ld_i32(cpu_index, tcg_env, + -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index)); + tcg_gen_call2(cb->cond.f.vcpu_udata, cb->cond.info, NULL, + tcgv_i32_temp(cpu_index), + tcgv_ptr_temp(tcg_constant_ptr(cb->userp))); + gen_set_label(after_cb); + + tcg_temp_free_i64(val); + tcg_temp_free_i32(cpu_index); + tcg_temp_free_ptr(ptr); +} + static void gen_inline_add_u64_cb(struct qemu_plugin_dyn_cb *cb) { TCGv_ptr ptr = gen_plugin_u64_ptr(cb->inline_insn.entry); @@ -177,6 +222,9 @@ static void inject_cb(struct qemu_plugin_dyn_cb *cb) case PLUGIN_CB_REGULAR: gen_udata_cb(cb); break; + case PLUGIN_CB_COND: + gen_udata_cond_cb(cb); + break; case PLUGIN_CB_INLINE_ADD_U64: gen_inline_add_u64_cb(cb); break; |