+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 TCGOp *append_cond_udata_cb(const struct qemu_plugin_dyn_cb *cb,
+ TCGOp *begin_op, TCGOp *op, int *cb_idx)
+{
+ char *ptr = cb->cond_cb.entry.score->data->data;
+ size_t elem_size = g_array_get_element_size(
+ cb->cond_cb.entry.score->data);
+ size_t offset = cb->cond_cb.entry.offset;
+ /* Condition should be negated, as calling the cb is the "else" path */
+ TCGCond cond = tcg_invert_cond(plugin_cond_to_tcgcond(cb->cond_cb.cond));
+
+ op = copy_const_ptr(&begin_op, op, ptr);
+ op = copy_ld_i32(&begin_op, op);
+ op = copy_mul_i32(&begin_op, op, elem_size);
+ op = copy_ext_i32_ptr(&begin_op, op);
+ op = copy_const_ptr(&begin_op, op, ptr + offset);
+ op = copy_add_ptr(&begin_op, op);
+ op = copy_ld_i64(&begin_op, op);
+ op = copy_brcondi_i64(&begin_op, op, cond, cb->cond_cb.imm);
+ op = copy_call(&begin_op, op, cb->f.vcpu_udata, cb_idx);
+ op = copy_set_label(&begin_op, op);
+ return op;