On Fri, Sep 18, 2026 at 9:01 AM Richard Henderson <
[email protected]> wrote:
>
> (1) Put the comment before the implementation, not the header.
> That avoids whatever you're concerned about vs patch 2.
>
> (2) Don't pass an extra argument that changes behavior like this.
> Better to have two separate functions, each doing one thing.
>
> (3) Maybe better to place the functions in cpu-exec-common.c, so that
> the compiler can see all the definitions at once.
>
>
> r~

 accel/tcg/gen-helpers.c          |  27 ++++++++
 accel/tcg/meson.build            |   1 +
 include/accel/tcg/gen-helpers.h  |  37 ++++++++++
 include/exec/helper-gen-common.h |   2 +
 include/exec/helper-impl.h       | 146
+++++++++++++++++++++++++++++++++++++++
 5 files changed, 213 insertions(+)

diff --git a/accel/tcg/gen-helpers.c b/accel/tcg/gen-helpers.c
new file mode 100644
index 00000000000..212f08cf844
--- /dev/null
+++ b/accel/tcg/gen-helpers.c
@@ -0,0 +1,27 @@
+/*
+ * Shared TCG helpers implemented with IMPL_HELPER_FLAGS_*.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "accel/tcg/cpu-loop.h"
+#include "accel/tcg/getpc.h"
+#include "exec/helper-impl.h"
+
+static G_NORETURN void helper_raise_excp(CPUArchState *env, uint32_t
exception)
+    __attribute__((noinline))
+{
+    cpu_loop_exit_excp(env_cpu(env), exception, 0);
+}
+
+IMPL_HELPER_FLAGS_2(raise_excp, TCG_CALL_NO_WG, noreturn, env, i32)
+
+static G_NORETURN void helper_raise_excp_restore(CPUArchState *env,
+                                                 uint32_t exception)
+    __attribute__((noinline))
+{
+    cpu_loop_exit_excp(env_cpu(env), exception, GETPC());
+}
+
+IMPL_HELPER_FLAGS_2(raise_excp_restore, TCG_CALL_NO_WG, noreturn, env, i32)
diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build
index 002aa8f4588..3f9afcc5f1d 100644
--- a/accel/tcg/meson.build
+++ b/accel/tcg/meson.build
@@ -7,6 +7,7 @@ tcg_ss = ss.source_set()
 tcg_ss.add(files(
   'cpu-exec.c',
   'cpu-exec-common.c',
+  'gen-helpers.c',
   'tcg-runtime.c',
   'tcg-runtime-gvec.c',
   'tb-maint.c',
diff --git a/include/accel/tcg/gen-helpers.h
b/include/accel/tcg/gen-helpers.h
new file mode 100644
index 00000000000..19787d6de24
--- /dev/null
+++ b/include/accel/tcg/gen-helpers.h
@@ -0,0 +1,37 @@
+/*
+ * Shared TCG gen_helper_* APIs implemented with IMPL_HELPER_FLAGS_*.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef ACCEL_TCG_GEN_HELPERS_H
+#define ACCEL_TCG_GEN_HELPERS_H
+
+#ifndef CONFIG_TCG
+#error Can only include this header with TCG
+#endif
+
+#include "tcg/tcg.h"
+
+/**
+ * gen_helper_raise_excp:
+ * @env: CPU env (tcg_env)
+ * @exception: EXCP_* or target trap number
+ *
+ * Shared TCG exception raise without unwind. Body is helper_raise_excp
+ * in accel/tcg/gen-helpers.c. Exits via cpu_loop_exit_excp with
+ * host_pc 0.
+ */
+void gen_helper_raise_excp(TCGv_env env, TCGv_i32 exception);
+
+/**
+ * gen_helper_raise_excp_restore:
+ * @env: CPU env (tcg_env)
+ * @exception: EXCP_* or target trap number
+ *
+ * Shared TCG exception raise with GETPC() unwind. Body is
+ * helper_raise_excp_restore in accel/tcg/gen-helpers.c. Exits via
+ * cpu_loop_exit_excp.
+ */
+void gen_helper_raise_excp_restore(TCGv_env env, TCGv_i32 exception);
+
+#endif
diff --git a/include/exec/helper-gen-common.h
b/include/exec/helper-gen-common.h
index 834590dc4e5..16548830ec8 100644
--- a/include/exec/helper-gen-common.h
+++ b/include/exec/helper-gen-common.h
@@ -11,4 +11,6 @@
 #include "exec/helper-gen.h.inc"
 #undef  HELPER_H

+#include "accel/tcg/gen-helpers.h"
+
 #endif /* HELPER_GEN_COMMON_H */
diff --git a/include/exec/helper-impl.h b/include/exec/helper-impl.h
new file mode 100644
index 00000000000..d2797e5e6a7
--- /dev/null
+++ b/include/exec/helper-impl.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Implement a TCG helper in one .c file: static helper_info_* plus
+ * gen_helper_*. Same arguments as DEF_HELPER_FLAGS_N. Write
+ * HELPER(name) beside the invocation.
+ */
+#ifndef EXEC_HELPER_IMPL_H
+#define EXEC_HELPER_IMPL_H
+
+#include "tcg/tcg.h"
+#include "tcg/helper-info.h"
+#include "exec/helper-head.h.inc"
+
+#define IMPL_HELPER_FLAGS_0(name, flags, ret)                           \
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(name),                      \
+    .flags = flags | dh_callflag(ret),                                  \
+    .typemask = dh_typemask(ret, 0)                                     \
+};                                                                      \
+void glue(gen_helper_, name)(dh_retvar_decl0(ret))                      \
+{                                                                       \
+    tcg_gen_call0(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret));            \
+}
+
+#define IMPL_HELPER_FLAGS_1(name, flags, ret, t1)                       \
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(name),                      \
+    .flags = flags | dh_callflag(ret),                                  \
+    .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1)                \
+};                                                                      \
+void glue(gen_helper_, name)(dh_retvar_decl(ret)                        \
+    dh_arg_decl(t1, 1))                                                 \
+{                                                                       \
+    tcg_gen_call1(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret),             \
+                  dh_arg(t1, 1));                                       \
+}
+
+#define IMPL_HELPER_FLAGS_2(name, flags, ret, t1, t2)                   \
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(name),                      \
+    .flags = flags | dh_callflag(ret),                                  \
+    .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1)                \
+              | dh_typemask(t2, 2)                                      \
+};                                                                      \
+void glue(gen_helper_, name)(dh_retvar_decl(ret)                        \
+    dh_arg_decl(t1, 1), dh_arg_decl(t2, 2))                             \
+{                                                                       \
+    tcg_gen_call2(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret),             \
+                  dh_arg(t1, 1), dh_arg(t2, 2));                        \
+}
+
+#define IMPL_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3)               \
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(name),                      \
+    .flags = flags | dh_callflag(ret),                                  \
+    .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1)                \
+              | dh_typemask(t2, 2) | dh_typemask(t3, 3)                 \
+};                                                                      \
+void glue(gen_helper_, name)(dh_retvar_decl(ret)                        \
+    dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3))         \
+{                                                                       \
+    tcg_gen_call3(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret),             \
+                  dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3));         \
+}
+
+#define IMPL_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4)           \
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(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)                                      \
+};                                                                      \
+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(t4, 4))                             \
+{                                                                       \
+    tcg_gen_call4(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret),             \
+                  dh_arg(t1, 1), dh_arg(t2, 2),                         \
+                  dh_arg(t3, 3), dh_arg(t4, 4));                        \
+}
+
+#define IMPL_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5)       \
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(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)                 \
+};                                                                      \
+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(t4, 4), dh_arg_decl(t5, 5))                             \
+{                                                                       \
+    tcg_gen_call5(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret),             \
+                  dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3),          \
+                  dh_arg(t4, 4), dh_arg(t5, 5));                        \
+}
+
+#define IMPL_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6)   \
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(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)                                      \
+};                                                                      \
+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(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6))         \
+{                                                                       \
+    tcg_gen_call6(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret),             \
+                  dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3),          \
+                  dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6));         \
+}
+
+#define IMPL_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7)\
+static TCGHelperInfo glue(helper_info_, name) = {                       \
+    .func = HELPER(name), .name = stringify(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)                 \
+};                                                                      \
+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(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6),         \
+    dh_arg_decl(t7, 7))                                                 \
+{                                                                       \
+    tcg_gen_call7(glue(helper_info_,name).func,                         \
+                  &glue(helper_info_,name), dh_retvar(ret),             \
+                  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(t7, 7));                                       \
+}
+
+#endif /* EXEC_HELPER_IMPL_H */

Do you mean doing like this?


--
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo

Reply via email to