Emilio G. Cota writes:
> This takes the TCGHelperInfo directly, which will allow us to generate
> helpers at run-time.
>
> Signed-off-by: Emilio G. Cota
Reviewed-by: Alex Bennée
> ---
> tcg/tcg.h | 2 ++
> tcg/tcg.c | 50 +-
> 2 files changed, 47 insertions(+), 5 deletions(-)
>
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index 9f9643b470..3fa434d891 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -1077,6 +1077,8 @@ do {\
> bool tcg_op_supported(TCGOpcode op);
>
> void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
> +void tcg_gen_runtime_helper(const TCGHelperInfo *orig, TCGTemp *ret, int
> nargs,
> +TCGTemp **args);
>
> TCGOp *tcg_emit_op(TCGOpcode opc);
> void tcg_op_remove(TCGContext *s, TCGOp *op);
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index 08b6926894..87e02da740 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -1642,15 +1642,13 @@ bool tcg_op_supported(TCGOpcode op)
> /* Note: we convert the 64 bit args to 32 bit and do some alignment
> and endian swap. Maybe it would be better to do the alignment
> and endian swap in tcg_reg_alloc_call(). */
> -void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
> +static void do_tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, int nargs,
> + TCGTemp **args)
> {
> int i, real_args, nb_rets, pi;
> unsigned sizemask, flags;
> -TCGHelperInfo *info;
> -uint32_t hash = tcg_helper_func_hash(func);
> TCGOp *op;
>
> -info = qht_lookup_custom(&helper_table, func, hash,
> tcg_helper_lookup_cmp);
> flags = info->flags;
> sizemask = info->sizemask;
>
> @@ -1774,7 +1772,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs,
> TCGTemp **args)
> op->args[pi++] = temp_arg(args[i]);
> real_args++;
> }
> -op->args[pi++] = (uintptr_t)func;
> +op->args[pi++] = (uintptr_t)info->func;
> op->args[pi++] = flags;
> TCGOP_CALLI(op) = real_args;
>
> @@ -1812,6 +1810,48 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int
> nargs, TCGTemp **args)
> #endif /* TCG_TARGET_EXTEND_ARGS */
> }
>
> +void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
> +{
> +TCGHelperInfo *info;
> +uint32_t hash = tcg_helper_func_hash(func);
> +
> +/*
> + * Here we can get away with tcg_helper_lookup_cmp, which only looks
> + * at the function pointer, since we have the compile-time guarantee
> + * that @func can only be in one TCGHelperInfo.
> + */
> +info = qht_lookup_custom(&helper_table, func, hash,
> tcg_helper_lookup_cmp);
> +do_tcg_gen_callN(info, ret, nargs, args);
> +}
> +
> +void tcg_gen_runtime_helper(const TCGHelperInfo *orig, TCGTemp *ret, int
> nargs,
> +TCGTemp **args)
> +{
> +TCGHelperInfo *info;
> +uint32_t hash = tcg_helper_func_hash(orig->func);
> +
> +/*
> + * Use the full TCGHelperInfo lookup, since there is no guarantee that
> func
> + * will be unique to each TCGHelperInfo. For instance, we could have the
> + * same helper function registered in several TCGHelperInfo's, each of
> them
> + * with different flags.
> + */
> +info = qht_lookup(&helper_table, orig, hash);
> +if (info == NULL) {
> +void *existing = NULL;
> +
> +/* @orig might be in the stack, so we need to allocate a new struct
> */
> +info = g_new(TCGHelperInfo, 1);
> +memcpy(info, orig, sizeof(TCGHelperInfo));
> +qht_insert(&helper_table, info, hash, &existing);
> +if (unlikely(existing)) {
> +g_free(info);
> +info = existing;
> +}
> +}
> +do_tcg_gen_callN(info, ret, nargs, args);
> +}
> +
> static void tcg_reg_alloc_start(TCGContext *s)
> {
> int i, n;
--
Alex Bennée