mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-10-14 23:13:30 +00:00
tcg: Pass TCGHelperInfo to tcg_gen_callN
In preparation for compiling tcg/ only once, eliminate the all_helpers array. Instantiate the info structs for the generic helpers in accel/tcg/, and the structs for the target-specific helpers in each translate.c. Since we don't see all of the info structs at startup, initialize at first use, using g_once_init_* to make sure we don't race while doing so. Reviewed-by: Anton Johansson <anjo@rev.ng> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
0f4e14c25a
commit
d53106c997
|
@ -154,6 +154,7 @@ F: include/exec/exec-all.h
|
||||||
F: include/exec/tb-flush.h
|
F: include/exec/tb-flush.h
|
||||||
F: include/exec/target_long.h
|
F: include/exec/target_long.h
|
||||||
F: include/exec/helper*.h
|
F: include/exec/helper*.h
|
||||||
|
F: include/exec/helper-info.c.inc
|
||||||
F: include/sysemu/cpus.h
|
F: include/sysemu/cpus.h
|
||||||
F: include/sysemu/tcg.h
|
F: include/sysemu/tcg.h
|
||||||
F: include/hw/core/tcg-cpu-ops.h
|
F: include/hw/core/tcg-cpu-ops.h
|
||||||
|
|
|
@ -49,6 +49,11 @@
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/plugin-gen.h"
|
#include "exec/plugin-gen.h"
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
|
#include "exec/helper-proto.h"
|
||||||
|
|
||||||
|
#define HELPER_H "accel/tcg/plugin-helpers.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_SOFTMMU
|
||||||
# define CONFIG_SOFTMMU_GATE 1
|
# define CONFIG_SOFTMMU_GATE 1
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
|
|
||||||
|
#define HELPER_H "accel/tcg/tcg-runtime.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
/* 32-bit helpers */
|
/* 32-bit helpers */
|
||||||
|
|
||||||
int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2)
|
int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2)
|
||||||
|
|
|
@ -1,81 +1,96 @@
|
||||||
/* Helper file for declaring TCG helper functions.
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
This one expands generation functions for tcg opcodes. */
|
/*
|
||||||
|
* Helper file for declaring TCG helper functions.
|
||||||
|
* This one expands generation functions for tcg opcodes.
|
||||||
|
* Define HELPER_H for the header file to be expanded,
|
||||||
|
* and static inline to change from global file scope.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef HELPER_GEN_H
|
#ifndef HELPER_GEN_H
|
||||||
#define HELPER_GEN_H
|
#define HELPER_GEN_H
|
||||||
|
|
||||||
|
#include "tcg/tcg.h"
|
||||||
|
#include "tcg/helper-info.h"
|
||||||
#include "exec/helper-head.h"
|
#include "exec/helper-head.h"
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
|
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
|
||||||
{ \
|
{ \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 0, NULL); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 0, NULL); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
|
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
dh_arg_decl(t1, 1)) \
|
dh_arg_decl(t1, 1)) \
|
||||||
{ \
|
{ \
|
||||||
TCGTemp *args[1] = { dh_arg(t1, 1) }; \
|
TCGTemp *args[1] = { dh_arg(t1, 1) }; \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 1, args); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 1, args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
|
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
|
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
|
||||||
{ \
|
{ \
|
||||||
TCGTemp *args[2] = { dh_arg(t1, 1), dh_arg(t2, 2) }; \
|
TCGTemp *args[2] = { dh_arg(t1, 1), dh_arg(t2, 2) }; \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 2, args); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 2, args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
|
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
|
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
|
||||||
{ \
|
{ \
|
||||||
TCGTemp *args[3] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3) }; \
|
TCGTemp *args[3] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3) }; \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 3, args); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 3, args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
|
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
|
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
|
||||||
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
|
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
|
||||||
{ \
|
{ \
|
||||||
TCGTemp *args[4] = { dh_arg(t1, 1), dh_arg(t2, 2), \
|
TCGTemp *args[4] = { dh_arg(t1, 1), dh_arg(t2, 2), \
|
||||||
dh_arg(t3, 3), dh_arg(t4, 4) }; \
|
dh_arg(t3, 3), dh_arg(t4, 4) }; \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 4, args); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 4, args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
|
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
|
||||||
{ \
|
{ \
|
||||||
TCGTemp *args[5] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
TCGTemp *args[5] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||||
dh_arg(t4, 4), dh_arg(t5, 5) }; \
|
dh_arg(t4, 4), dh_arg(t5, 5) }; \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 5, args); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 5, args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
|
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
|
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
|
||||||
{ \
|
{ \
|
||||||
TCGTemp *args[6] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
TCGTemp *args[6] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||||
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6) }; \
|
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6) }; \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 6, args); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 6, args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7)\
|
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7)\
|
||||||
|
extern TCGHelperInfo glue(helper_info_, name); \
|
||||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
|
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
|
||||||
dh_arg_decl(t7, 7)) \
|
dh_arg_decl(t7, 7)) \
|
||||||
{ \
|
{ \
|
||||||
TCGTemp *args[7] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
TCGTemp *args[7] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||||
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
|
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
|
||||||
dh_arg(t7, 7) }; \
|
dh_arg(t7, 7) }; \
|
||||||
tcg_gen_callN(HELPER(name), dh_retvar(ret), 7, args); \
|
tcg_gen_callN(&glue(helper_info_, name), dh_retvar(ret), 7, args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
|
@ -90,6 +105,5 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||||
#undef DEF_HELPER_FLAGS_5
|
#undef DEF_HELPER_FLAGS_5
|
||||||
#undef DEF_HELPER_FLAGS_6
|
#undef DEF_HELPER_FLAGS_6
|
||||||
#undef DEF_HELPER_FLAGS_7
|
#undef DEF_HELPER_FLAGS_7
|
||||||
#undef GEN_HELPER
|
|
||||||
|
|
||||||
#endif /* HELPER_GEN_H */
|
#endif /* HELPER_GEN_H */
|
||||||
|
|
96
include/exec/helper-info.c.inc
Normal file
96
include/exec/helper-info.c.inc
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* Helper file for declaring TCG helper functions.
|
||||||
|
* This one expands info structures for tcg helpers.
|
||||||
|
* Define HELPER_H for the header file to be expanded.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tcg/tcg.h"
|
||||||
|
#include "tcg/helper-info.h"
|
||||||
|
#include "exec/helper-head.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need one more level of indirection before stringification
|
||||||
|
* to get all the macros expanded first.
|
||||||
|
*/
|
||||||
|
#define str(s) #s
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_0(NAME, FLAGS, RET) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_1(NAME, FLAGS, RET, T1) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_2(NAME, FLAGS, RET, T1, T2) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||||
|
| dh_typemask(T2, 2) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, RET, T1, T2, T3) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||||
|
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_4(NAME, FLAGS, RET, T1, T2, T3, T4) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||||
|
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||||
|
| dh_typemask(T4, 4) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_5(NAME, FLAGS, RET, T1, T2, T3, T4, T5) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||||
|
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||||
|
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_6(NAME, FLAGS, RET, T1, T2, T3, T4, T5, T6) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||||
|
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||||
|
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
|
||||||
|
| dh_typemask(T6, 6) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_HELPER_FLAGS_7(NAME, FLAGS, RET, T1, T2, T3, T4, T5, T6, T7) \
|
||||||
|
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||||
|
.func = HELPER(NAME), .name = str(NAME), \
|
||||||
|
.flags = FLAGS | dh_callflag(RET), \
|
||||||
|
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||||
|
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||||
|
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
|
||||||
|
| dh_typemask(T6, 6) | dh_typemask(T7, 7) \
|
||||||
|
};
|
||||||
|
|
||||||
|
#include HELPER_H
|
||||||
|
|
||||||
|
#undef str
|
||||||
|
#undef DEF_HELPER_FLAGS_0
|
||||||
|
#undef DEF_HELPER_FLAGS_1
|
||||||
|
#undef DEF_HELPER_FLAGS_2
|
||||||
|
#undef DEF_HELPER_FLAGS_3
|
||||||
|
#undef DEF_HELPER_FLAGS_4
|
||||||
|
#undef DEF_HELPER_FLAGS_5
|
||||||
|
#undef DEF_HELPER_FLAGS_6
|
||||||
|
#undef DEF_HELPER_FLAGS_7
|
|
@ -1,75 +0,0 @@
|
||||||
/* Helper file for declaring TCG helper functions.
|
|
||||||
This one defines data structures private to tcg.c. */
|
|
||||||
|
|
||||||
#ifndef HELPER_TCG_H
|
|
||||||
#define HELPER_TCG_H
|
|
||||||
|
|
||||||
#include "exec/helper-head.h"
|
|
||||||
|
|
||||||
/* Need one more level of indirection before stringification
|
|
||||||
to get all the macros expanded first. */
|
|
||||||
#define str(s) #s
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_0(NAME, FLAGS, ret) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), \
|
|
||||||
.flags = FLAGS | dh_callflag(ret), \
|
|
||||||
.typemask = dh_typemask(ret, 0) },
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_1(NAME, FLAGS, ret, t1) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), \
|
|
||||||
.flags = FLAGS | dh_callflag(ret), \
|
|
||||||
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) },
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_2(NAME, FLAGS, ret, t1, t2) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), \
|
|
||||||
.flags = FLAGS | dh_callflag(ret), \
|
|
||||||
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
|
|
||||||
| dh_typemask(t2, 2) },
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, ret, t1, t2, t3) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), \
|
|
||||||
.flags = FLAGS | dh_callflag(ret), \
|
|
||||||
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
|
|
||||||
| dh_typemask(t2, 2) | dh_typemask(t3, 3) },
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_4(NAME, FLAGS, ret, t1, t2, t3, t4) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), \
|
|
||||||
.flags = FLAGS | dh_callflag(ret), \
|
|
||||||
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
|
|
||||||
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) },
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_5(NAME, FLAGS, ret, t1, t2, t3, t4, t5) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), \
|
|
||||||
.flags = FLAGS | dh_callflag(ret), \
|
|
||||||
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
|
|
||||||
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
|
|
||||||
| dh_typemask(t5, 5) },
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_6(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), \
|
|
||||||
.flags = FLAGS | dh_callflag(ret), \
|
|
||||||
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
|
|
||||||
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
|
|
||||||
| dh_typemask(t5, 5) | dh_typemask(t6, 6) },
|
|
||||||
|
|
||||||
#define DEF_HELPER_FLAGS_7(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6, t7) \
|
|
||||||
{ .func = HELPER(NAME), .name = str(NAME), .flags = FLAGS, \
|
|
||||||
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
|
|
||||||
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
|
|
||||||
| dh_typemask(t5, 5) | dh_typemask(t6, 6) | dh_typemask(t7, 7) },
|
|
||||||
|
|
||||||
#include "helper.h"
|
|
||||||
#include "accel/tcg/tcg-runtime.h"
|
|
||||||
#include "accel/tcg/plugin-helpers.h"
|
|
||||||
|
|
||||||
#undef str
|
|
||||||
#undef DEF_HELPER_FLAGS_0
|
|
||||||
#undef DEF_HELPER_FLAGS_1
|
|
||||||
#undef DEF_HELPER_FLAGS_2
|
|
||||||
#undef DEF_HELPER_FLAGS_3
|
|
||||||
#undef DEF_HELPER_FLAGS_4
|
|
||||||
#undef DEF_HELPER_FLAGS_5
|
|
||||||
#undef DEF_HELPER_FLAGS_6
|
|
||||||
#undef DEF_HELPER_FLAGS_7
|
|
||||||
|
|
||||||
#endif /* HELPER_TCG_H */
|
|
|
@ -131,6 +131,7 @@ typedef struct ReservedRegion ReservedRegion;
|
||||||
typedef struct SavedIOTLB SavedIOTLB;
|
typedef struct SavedIOTLB SavedIOTLB;
|
||||||
typedef struct SHPCDevice SHPCDevice;
|
typedef struct SHPCDevice SHPCDevice;
|
||||||
typedef struct SSIBus SSIBus;
|
typedef struct SSIBus SSIBus;
|
||||||
|
typedef struct TCGHelperInfo TCGHelperInfo;
|
||||||
typedef struct TranslationBlock TranslationBlock;
|
typedef struct TranslationBlock TranslationBlock;
|
||||||
typedef struct VirtIODevice VirtIODevice;
|
typedef struct VirtIODevice VirtIODevice;
|
||||||
typedef struct Visitor Visitor;
|
typedef struct Visitor Visitor;
|
||||||
|
|
|
@ -40,12 +40,17 @@ typedef struct TCGCallArgumentLoc {
|
||||||
unsigned tmp_subindex : 2;
|
unsigned tmp_subindex : 2;
|
||||||
} TCGCallArgumentLoc;
|
} TCGCallArgumentLoc;
|
||||||
|
|
||||||
typedef struct TCGHelperInfo {
|
struct TCGHelperInfo {
|
||||||
void *func;
|
void *func;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
/* Used with g_once_init_enter. */
|
||||||
#ifdef CONFIG_TCG_INTERPRETER
|
#ifdef CONFIG_TCG_INTERPRETER
|
||||||
ffi_cif *cif;
|
ffi_cif *cif;
|
||||||
|
#else
|
||||||
|
uintptr_t init;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned typemask : 32;
|
unsigned typemask : 32;
|
||||||
unsigned flags : 8;
|
unsigned flags : 8;
|
||||||
unsigned nr_in : 8;
|
unsigned nr_in : 8;
|
||||||
|
@ -54,6 +59,6 @@ typedef struct TCGHelperInfo {
|
||||||
|
|
||||||
/* Maximum physical arguments are constrained by TCG_TYPE_I128. */
|
/* Maximum physical arguments are constrained by TCG_TYPE_I128. */
|
||||||
TCGCallArgumentLoc in[MAX_CALL_IARGS * (128 / TCG_TARGET_REG_BITS)];
|
TCGCallArgumentLoc in[MAX_CALL_IARGS * (128 / TCG_TARGET_REG_BITS)];
|
||||||
} TCGHelperInfo;
|
};
|
||||||
|
|
||||||
#endif /* TCG_HELPER_INFO_H */
|
#endif /* TCG_HELPER_INFO_H */
|
||||||
|
|
|
@ -937,7 +937,7 @@ typedef struct TCGTargetOpDef {
|
||||||
|
|
||||||
bool tcg_op_supported(TCGOpcode op);
|
bool tcg_op_supported(TCGOpcode op);
|
||||||
|
|
||||||
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
|
void tcg_gen_callN(TCGHelperInfo *, TCGTemp *ret, int nargs, TCGTemp **args);
|
||||||
|
|
||||||
TCGOp *tcg_emit_op(TCGOpcode opc, unsigned nargs);
|
TCGOp *tcg_emit_op(TCGOpcode opc, unsigned nargs);
|
||||||
void tcg_op_remove(TCGContext *s, TCGOp *op);
|
void tcg_op_remove(TCGContext *s, TCGOp *op);
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#undef ALPHA_DEBUG_DISAS
|
#undef ALPHA_DEBUG_DISAS
|
||||||
#define CONFIG_SOFTFLOAT_INLINE
|
#define CONFIG_SOFTFLOAT_INLINE
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "cpregs.h"
|
#include "cpregs.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
|
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
|
||||||
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
|
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
#include "exec/gen-icount.h"
|
#include "exec/gen-icount.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define if you want a BREAK instruction translated to a breakpoint
|
* Define if you want a BREAK instruction translated to a breakpoint
|
||||||
* Active debugging connection is assumed
|
* Active debugging connection is assumed
|
||||||
|
|
|
@ -34,11 +34,13 @@
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
#include "crisv32-decode.h"
|
#include "crisv32-decode.h"
|
||||||
#include "qemu/qemu-print.h"
|
#include "qemu/qemu-print.h"
|
||||||
|
|
||||||
#include "exec/helper-gen.h"
|
#include "exec/helper-gen.h"
|
||||||
|
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
#define DISAS_CRIS 0
|
#define DISAS_CRIS 0
|
||||||
#if DISAS_CRIS
|
#if DISAS_CRIS
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
#include "genptr.h"
|
#include "genptr.h"
|
||||||
#include "printinsn.h"
|
#include "printinsn.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#include "analyze_funcs_generated.c.inc"
|
#include "analyze_funcs_generated.c.inc"
|
||||||
|
|
||||||
typedef void (*AnalyzeInsn)(DisasContext *ctx);
|
typedef void (*AnalyzeInsn)(DisasContext *ctx);
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
/* Since we have a distinction between register size and address size,
|
/* Since we have a distinction between register size and address size,
|
||||||
we need to redefine all of these. */
|
we need to redefine all of these. */
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,11 @@
|
||||||
|
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
#define PREFIX_REPZ 0x01
|
#define PREFIX_REPZ 0x01
|
||||||
#define PREFIX_REPNZ 0x02
|
#define PREFIX_REPNZ 0x02
|
||||||
#define PREFIX_LOCK 0x04
|
#define PREFIX_LOCK 0x04
|
||||||
|
|
|
@ -26,6 +26,10 @@ static TCGv cpu_lladdr, cpu_llval;
|
||||||
|
|
||||||
#include "exec/gen-icount.h"
|
#include "exec/gen-icount.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#define DISAS_STOP DISAS_TARGET_0
|
#define DISAS_STOP DISAS_TARGET_0
|
||||||
#define DISAS_EXIT DISAS_TARGET_1
|
#define DISAS_EXIT DISAS_TARGET_1
|
||||||
#define DISAS_EXIT_UPDATE DISAS_TARGET_2
|
#define DISAS_EXIT_UPDATE DISAS_TARGET_2
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "fpu/softfloat.h"
|
#include "fpu/softfloat.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
//#define DEBUG_DISPATCH 1
|
//#define DEBUG_DISPATCH 1
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
|
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#define EXTRACT_FIELD(src, start, end) \
|
#define EXTRACT_FIELD(src, start, end) \
|
||||||
(((src) >> start) & ((1 << (end - start + 1)) - 1))
|
(((src) >> start) & ((1 << (end - start + 1)) - 1))
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
#include "fpu_helper.h"
|
#include "fpu_helper.h"
|
||||||
#include "translate.h"
|
#include "translate.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Many sysemu-only helpers are not reachable for user-only.
|
* Many sysemu-only helpers are not reachable for user-only.
|
||||||
* Define stub generators here, so that we need not either sprinkle
|
* Define stub generators here, so that we need not either sprinkle
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
#include "exec/gen-icount.h"
|
#include "exec/gen-icount.h"
|
||||||
#include "semihosting/semihost.h"
|
#include "semihosting/semihost.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
/* is_jmp field values */
|
/* is_jmp field values */
|
||||||
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
|
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
|
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
/* is_jmp field values */
|
/* is_jmp field values */
|
||||||
#define DISAS_EXIT DISAS_TARGET_0 /* force exit to main loop */
|
#define DISAS_EXIT DISAS_TARGET_0 /* force exit to main loop */
|
||||||
#define DISAS_JUMP DISAS_TARGET_1 /* exit via jmp_pc/jmp_pc_imm */
|
#define DISAS_JUMP DISAS_TARGET_1 /* exit via jmp_pc/jmp_pc_imm */
|
||||||
|
|
|
@ -41,6 +41,10 @@
|
||||||
#include "qemu/qemu-print.h"
|
#include "qemu/qemu-print.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#define CPU_SINGLE_STEP 0x1
|
#define CPU_SINGLE_STEP 0x1
|
||||||
#define CPU_BRANCH_STEP 0x2
|
#define CPU_BRANCH_STEP 0x2
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,10 @@
|
||||||
#include "instmap.h"
|
#include "instmap.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
/* global register indices */
|
/* global register indices */
|
||||||
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
|
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
|
||||||
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
|
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
typedef struct DisasContext {
|
typedef struct DisasContext {
|
||||||
DisasContextBase base;
|
DisasContextBase base;
|
||||||
CPURXState *env;
|
CPURXState *env;
|
||||||
|
|
|
@ -46,6 +46,10 @@
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "qemu/atomic128.h"
|
#include "qemu/atomic128.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
/* Information that (most) every instruction needs to manipulate. */
|
/* Information that (most) every instruction needs to manipulate. */
|
||||||
typedef struct DisasContext DisasContext;
|
typedef struct DisasContext DisasContext;
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "qemu/qemu-print.h"
|
#include "qemu/qemu-print.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
typedef struct DisasContext {
|
typedef struct DisasContext {
|
||||||
DisasContextBase base;
|
DisasContextBase base;
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "asi.h"
|
#include "asi.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#define DYNAMIC_PC 1 /* dynamic pc value */
|
#define DYNAMIC_PC 1 /* dynamic pc value */
|
||||||
#define JUMP_PC 2 /* dynamic pc value which takes only two values
|
#define JUMP_PC 2 /* dynamic pc value which takes only two values
|
||||||
|
|
|
@ -33,6 +33,11 @@
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCG registers
|
* TCG registers
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,6 +45,10 @@
|
||||||
|
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "helper.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
|
|
||||||
struct DisasContext {
|
struct DisasContext {
|
||||||
DisasContextBase base;
|
DisasContextBase base;
|
||||||
|
|
108
tcg/tcg.c
108
tcg/tcg.c
|
@ -848,13 +848,6 @@ void tcg_pool_reset(TCGContext *s)
|
||||||
s->pool_current = NULL;
|
s->pool_current = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
|
|
||||||
static TCGHelperInfo all_helpers[] = {
|
|
||||||
#include "exec/helper-tcg.h"
|
|
||||||
};
|
|
||||||
static GHashTable *helper_table;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create TCGHelperInfo structures for "tcg/tcg-ldst.h" functions,
|
* Create TCGHelperInfo structures for "tcg/tcg-ldst.h" functions,
|
||||||
* akin to what "exec/helper-tcg.h" does with DEF_HELPER_FLAGS_N.
|
* akin to what "exec/helper-tcg.h" does with DEF_HELPER_FLAGS_N.
|
||||||
|
@ -964,57 +957,45 @@ static ffi_type *typecode_to_ffi(int argmask)
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_ffi_layouts(void)
|
static ffi_cif *init_ffi_layout(TCGHelperInfo *info)
|
||||||
{
|
{
|
||||||
/* g_direct_hash/equal for direct comparisons on uint32_t. */
|
unsigned typemask = info->typemask;
|
||||||
GHashTable *ffi_table = g_hash_table_new(NULL, NULL);
|
struct {
|
||||||
|
ffi_cif cif;
|
||||||
|
ffi_type *args[];
|
||||||
|
} *ca;
|
||||||
|
ffi_status status;
|
||||||
|
int nargs;
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
|
/* Ignoring the return type, find the last non-zero field. */
|
||||||
TCGHelperInfo *info = &all_helpers[i];
|
nargs = 32 - clz32(typemask >> 3);
|
||||||
unsigned typemask = info->typemask;
|
nargs = DIV_ROUND_UP(nargs, 3);
|
||||||
gpointer hash = (gpointer)(uintptr_t)typemask;
|
assert(nargs <= MAX_CALL_IARGS);
|
||||||
struct {
|
|
||||||
ffi_cif cif;
|
|
||||||
ffi_type *args[];
|
|
||||||
} *ca;
|
|
||||||
ffi_status status;
|
|
||||||
int nargs;
|
|
||||||
ffi_cif *cif;
|
|
||||||
|
|
||||||
cif = g_hash_table_lookup(ffi_table, hash);
|
ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));
|
||||||
if (cif) {
|
ca->cif.rtype = typecode_to_ffi(typemask & 7);
|
||||||
info->cif = cif;
|
ca->cif.nargs = nargs;
|
||||||
continue;
|
|
||||||
|
if (nargs != 0) {
|
||||||
|
ca->cif.arg_types = ca->args;
|
||||||
|
for (int j = 0; j < nargs; ++j) {
|
||||||
|
int typecode = extract32(typemask, (j + 1) * 3, 3);
|
||||||
|
ca->args[j] = typecode_to_ffi(typecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignoring the return type, find the last non-zero field. */
|
|
||||||
nargs = 32 - clz32(typemask >> 3);
|
|
||||||
nargs = DIV_ROUND_UP(nargs, 3);
|
|
||||||
assert(nargs <= MAX_CALL_IARGS);
|
|
||||||
|
|
||||||
ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));
|
|
||||||
ca->cif.rtype = typecode_to_ffi(typemask & 7);
|
|
||||||
ca->cif.nargs = nargs;
|
|
||||||
|
|
||||||
if (nargs != 0) {
|
|
||||||
ca->cif.arg_types = ca->args;
|
|
||||||
for (int j = 0; j < nargs; ++j) {
|
|
||||||
int typecode = extract32(typemask, (j + 1) * 3, 3);
|
|
||||||
ca->args[j] = typecode_to_ffi(typecode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,
|
|
||||||
ca->cif.rtype, ca->cif.arg_types);
|
|
||||||
assert(status == FFI_OK);
|
|
||||||
|
|
||||||
cif = &ca->cif;
|
|
||||||
info->cif = cif;
|
|
||||||
g_hash_table_insert(ffi_table, hash, (gpointer)cif);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_destroy(ffi_table);
|
status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,
|
||||||
|
ca->cif.rtype, ca->cif.arg_types);
|
||||||
|
assert(status == FFI_OK);
|
||||||
|
|
||||||
|
return &ca->cif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HELPER_INFO_INIT(I) (&(I)->cif)
|
||||||
|
#define HELPER_INFO_INIT_VAL(I) init_ffi_layout(I)
|
||||||
|
#else
|
||||||
|
#define HELPER_INFO_INIT(I) (&(I)->init)
|
||||||
|
#define HELPER_INFO_INIT_VAL(I) 1
|
||||||
#endif /* CONFIG_TCG_INTERPRETER */
|
#endif /* CONFIG_TCG_INTERPRETER */
|
||||||
|
|
||||||
static inline bool arg_slot_reg_p(unsigned arg_slot)
|
static inline bool arg_slot_reg_p(unsigned arg_slot)
|
||||||
|
@ -1327,16 +1308,6 @@ static void tcg_context_init(unsigned max_cpus)
|
||||||
args_ct += n;
|
args_ct += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register helpers. */
|
|
||||||
/* Use g_direct_hash/equal for direct pointer comparisons on func. */
|
|
||||||
helper_table = g_hash_table_new(NULL, NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
|
|
||||||
init_call_layout(&all_helpers[i]);
|
|
||||||
g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
|
|
||||||
(gpointer)&all_helpers[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
init_call_layout(&info_helper_ld32_mmu);
|
init_call_layout(&info_helper_ld32_mmu);
|
||||||
init_call_layout(&info_helper_ld64_mmu);
|
init_call_layout(&info_helper_ld64_mmu);
|
||||||
init_call_layout(&info_helper_ld128_mmu);
|
init_call_layout(&info_helper_ld128_mmu);
|
||||||
|
@ -1344,10 +1315,6 @@ static void tcg_context_init(unsigned max_cpus)
|
||||||
init_call_layout(&info_helper_st64_mmu);
|
init_call_layout(&info_helper_st64_mmu);
|
||||||
init_call_layout(&info_helper_st128_mmu);
|
init_call_layout(&info_helper_st128_mmu);
|
||||||
|
|
||||||
#ifdef CONFIG_TCG_INTERPRETER
|
|
||||||
init_ffi_layouts();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tcg_target_init(s);
|
tcg_target_init(s);
|
||||||
process_op_defs(s);
|
process_op_defs(s);
|
||||||
|
|
||||||
|
@ -2141,15 +2108,18 @@ bool tcg_op_supported(TCGOpcode op)
|
||||||
|
|
||||||
static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs);
|
static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs);
|
||||||
|
|
||||||
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
|
void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, int nargs, TCGTemp **args)
|
||||||
{
|
{
|
||||||
const TCGHelperInfo *info;
|
|
||||||
TCGv_i64 extend_free[MAX_CALL_IARGS];
|
TCGv_i64 extend_free[MAX_CALL_IARGS];
|
||||||
int n_extend = 0;
|
int n_extend = 0;
|
||||||
TCGOp *op;
|
TCGOp *op;
|
||||||
int i, n, pi = 0, total_args;
|
int i, n, pi = 0, total_args;
|
||||||
|
|
||||||
info = g_hash_table_lookup(helper_table, (gpointer)func);
|
if (unlikely(g_once_init_enter(HELPER_INFO_INIT(info)))) {
|
||||||
|
init_call_layout(info);
|
||||||
|
g_once_init_leave(HELPER_INFO_INIT(info), HELPER_INFO_INIT_VAL(info));
|
||||||
|
}
|
||||||
|
|
||||||
total_args = info->nr_out + info->nr_in + 2;
|
total_args = info->nr_out + info->nr_in + 2;
|
||||||
op = tcg_op_alloc(INDEX_op_call, total_args);
|
op = tcg_op_alloc(INDEX_op_call, total_args);
|
||||||
|
|
||||||
|
@ -2216,7 +2186,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
op->args[pi++] = (uintptr_t)func;
|
op->args[pi++] = (uintptr_t)info->func;
|
||||||
op->args[pi++] = (uintptr_t)info;
|
op->args[pi++] = (uintptr_t)info;
|
||||||
tcg_debug_assert(pi == total_args);
|
tcg_debug_assert(pi == total_args);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue