aboutsummaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
Diffstat (limited to 'tcg')
-rw-r--r--tcg/tcg-op.h11
-rw-r--r--tcg/tcg-opc.h3
-rw-r--r--tcg/tcg.c22
-rw-r--r--tcg/tcg.h20
4 files changed, 56 insertions, 0 deletions
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 7c778f96f3..4af272daa5 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -833,6 +833,17 @@ void tcg_gen_goto_tb(unsigned idx);
*/
void tcg_gen_lookup_and_goto_ptr(void);
+static inline void tcg_gen_plugin_cb_start(unsigned from, unsigned type,
+ unsigned wr)
+{
+ tcg_gen_op3(INDEX_op_plugin_cb_start, from, type, wr);
+}
+
+static inline void tcg_gen_plugin_cb_end(void)
+{
+ tcg_emit_op(INDEX_op_plugin_cb_end);
+}
+
#if TARGET_LONG_BITS == 32
#define tcg_temp_new() tcg_temp_new_i32()
#define tcg_global_reg_new tcg_global_reg_new_i32
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 242d608e6d..9288a04946 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -198,6 +198,9 @@ DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
DEF(goto_ptr, 0, 1, 0,
TCG_OPF_BB_EXIT | TCG_OPF_BB_END | IMPL(TCG_TARGET_HAS_goto_ptr))
+DEF(plugin_cb_start, 0, 0, 3, TCG_OPF_NOT_PRESENT)
+DEF(plugin_cb_end, 0, 0, 0, TCG_OPF_NOT_PRESENT)
+
DEF(qemu_ld_i32, 1, TLADDR_ARGS, 1,
TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
DEF(qemu_st_i32, 0, TLADDR_ARGS + 1, 1,
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 16b2d0e0ec..5475d49ed1 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -736,6 +736,15 @@ void tcg_region_init(void)
#endif
}
+static void alloc_tcg_plugin_context(TCGContext *s)
+{
+#ifdef CONFIG_PLUGIN
+ s->plugin_tb = g_new0(struct qemu_plugin_tb, 1);
+ s->plugin_tb->insns =
+ g_ptr_array_new_with_free_func(qemu_plugin_insn_cleanup_fn);
+#endif
+}
+
/*
* All TCG threads except the parent (i.e. the one that called tcg_context_init
* and registered the target's TCG globals) must register with this function
@@ -780,6 +789,10 @@ void tcg_register_thread(void)
g_assert(n < ms->smp.max_cpus);
atomic_set(&tcg_ctxs[n], s);
+ if (n > 0) {
+ alloc_tcg_plugin_context(s);
+ }
+
tcg_ctx = s;
qemu_mutex_lock(&region.lock);
err = tcg_region_initial_alloc__locked(tcg_ctx);
@@ -976,6 +989,8 @@ void tcg_context_init(TCGContext *s)
indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[i];
}
+ alloc_tcg_plugin_context(s);
+
tcg_ctx = s;
/*
* In user-mode we simply share the init context among threads, since we
@@ -1681,6 +1696,13 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
flags = info->flags;
sizemask = info->sizemask;
+#ifdef CONFIG_PLUGIN
+ /* detect non-plugin helpers */
+ if (tcg_ctx->plugin_insn && unlikely(strncmp(info->name, "plugin_", 7))) {
+ tcg_ctx->plugin_insn->calls_helpers = true;
+ }
+#endif
+
#if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER)
/* We have 64-bit values in one register, but need to pass as two
diff --git a/tcg/tcg.h b/tcg/tcg.h
index a37181c899..d234b4c9a5 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -538,6 +538,9 @@ typedef struct TCGOp {
/* Next and previous opcodes. */
QTAILQ_ENTRY(TCGOp) link;
+#ifdef CONFIG_PLUGIN
+ QSIMPLEQ_ENTRY(TCGOp) plugin_link;
+#endif
/* Arguments for the opcode. */
TCGArg args[MAX_OPC_PARAM];
@@ -639,6 +642,23 @@ struct TCGContext {
TCGLabel *exitreq_label;
+#ifdef CONFIG_PLUGIN
+ /*
+ * We keep one plugin_tb struct per TCGContext. Note that on every TB
+ * translation we clear but do not free its contents; this way we
+ * avoid a lot of malloc/free churn, since after a few TB's it's
+ * unlikely that we'll need to allocate either more instructions or more
+ * space for instructions (for variable-instruction-length ISAs).
+ */
+ struct qemu_plugin_tb *plugin_tb;
+
+ /* descriptor of the instruction being translated */
+ struct qemu_plugin_insn *plugin_insn;
+
+ /* list to quickly access the injected ops */
+ QSIMPLEQ_HEAD(, TCGOp) plugin_ops;
+#endif
+
TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */