qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kohei Tokunaga <ktokunaga.mail@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Alex Bennée" <alex.bennee@linaro.org>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>,
	"Thomas Huth" <thuth@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Daniel P . Berrangé" <berrange@redhat.com>,
	"WANG Xuerui" <git@xen0n.name>,
	"Aurelien Jarno" <aurelien@aurel32.net>,
	"Huacai Chen" <chenhuacai@kernel.org>,
	"Jiaxun Yang" <jiaxun.yang@flygoat.com>,
	"Aleksandar Rikalo" <arikalo@gmail.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Alistair Francis" <Alistair.Francis@wdc.com>,
	"Stefan Weil" <sw@weilnetz.de>,
	qemu-arm@nongnu.org, qemu-riscv@nongnu.org,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Pierrick Bouvier" <pierrick.bouvier@linaro.org>,
	ktokunaga.mail@gmail.com
Subject: [PATCH v3 21/35] tcg/wasm: Add exit_tb/goto_tb/goto_ptr instructions
Date: Mon,  1 Sep 2025 20:44:23 +0900	[thread overview]
Message-ID: <f15853e3bc8c5e6b3a622de90dd14261cb9c82be.1756724464.git.ktokunaga.mail@gmail.com> (raw)
In-Reply-To: <cover.1756724464.git.ktokunaga.mail@gmail.com>

In the Wasm backend, each TB is compiled to a separeted Wasm module. Control
transfer between TBs (i.e. from one Wasm module to another) is handled by
the caller of the module.

The goto_tb and goto_ptr operations are implemented by returning control to
the caller using the return instruction. The destination TB's pointer is
passed to the caller via a shared WasmContext structure which is accessible
from both the Wasm module and the caller. This WasmContext must be provided
to the module as an argument.

If the destination TB is the current TB itself, there is no need to return
control to the caller. Instead, execution can jump directly to the top of
the loop within the TB.

The exit_tb operation sets the pointer in WasmContext to 0, indicating that
there is no destination TB.

TCI instructions are also generated in the same way as the original TCI
backend.

Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
---
 MAINTAINERS               |   1 +
 tcg/wasm.c                |  20 ++++++
 tcg/wasm.h                |  15 +++++
 tcg/wasm/tcg-target.c.inc | 136 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)
 create mode 100644 tcg/wasm.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 217bf2066c..d528b9ec90 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4004,6 +4004,7 @@ M: Kohei Tokunaga <ktokunaga.mail@gmail.com>
 S: Maintained
 F: tcg/wasm/
 F: tcg/wasm.c
+F: tcg/wasm.h
 
 Block drivers
 -------------
diff --git a/tcg/wasm.c b/tcg/wasm.c
index ca67436192..c54c5c5b2c 100644
--- a/tcg/wasm.c
+++ b/tcg/wasm.c
@@ -28,6 +28,11 @@ static void tci_args_l(uint32_t insn, const void *tb_ptr, void **l0)
     *l0 = diff ? (void *)tb_ptr + diff : NULL;
 }
 
+static void tci_args_r(uint32_t insn, TCGReg *r0)
+{
+    *r0 = extract32(insn, 8, 4);
+}
+
 static void tci_args_rl(uint32_t insn, const void *tb_ptr,
                         TCGReg *r0, void **l1)
 {
@@ -413,6 +418,21 @@ static uintptr_t tcg_qemu_tb_exec_tci(CPUArchState *env, const void *v_tb_ptr)
                 tb_ptr = ptr;
             }
             break;
+        case INDEX_op_exit_tb:
+            tci_args_l(insn, tb_ptr, &ptr);
+            return (uintptr_t)ptr;
+        case INDEX_op_goto_tb:
+            tci_args_l(insn, tb_ptr, &ptr);
+            tb_ptr = *(void **)ptr;
+            break;
+        case INDEX_op_goto_ptr:
+            tci_args_r(insn, &r0);
+            ptr = (void *)regs[r0];
+            if (!ptr) {
+                return 0;
+            }
+            tb_ptr = ptr;
+            break;
         default:
             g_assert_not_reached();
         }
diff --git a/tcg/wasm.h b/tcg/wasm.h
new file mode 100644
index 0000000000..9da38e4d0e
--- /dev/null
+++ b/tcg/wasm.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef TCG_WASM_H
+#define TCG_WASM_H
+
+/*
+ * WasmContext is a data shared among QEMU and wasm modules.
+ */
+struct WasmContext {
+    /*
+     * Pointer to the TB to be executed.
+     */
+    void *tb_ptr;
+};
+
+#endif
diff --git a/tcg/wasm/tcg-target.c.inc b/tcg/wasm/tcg-target.c.inc
index ca10f97ed8..c077c8ad7c 100644
--- a/tcg/wasm/tcg-target.c.inc
+++ b/tcg/wasm/tcg-target.c.inc
@@ -26,6 +26,7 @@
  */
 
 #include "qemu/queue.h"
+#include "../wasm.h"
 
 typedef uint32_t tcg_insn_unit_tci;
 
@@ -139,6 +140,9 @@ static const uint8_t tcg_target_reg_index[TCG_TARGET_NB_REGS] = {
 /* Global variable used for storing the current block index */
 #define BLOCK_IDX 16
 
+/* Local variable pointing to WasmContext */
+#define CTX_IDX 0
+
 typedef enum {
     OPC_UNREACHABLE = 0x00,
     OPC_LOOP = 0x03,
@@ -146,6 +150,8 @@ typedef enum {
     OPC_ELSE = 0x05,
     OPC_END = 0x0b,
     OPC_BR = 0x0c,
+    OPC_RETURN = 0x0f,
+    OPC_LOCAL_GET = 0x20,
     OPC_GLOBAL_GET = 0x23,
     OPC_GLOBAL_SET = 0x24,
 
@@ -751,6 +757,81 @@ static void tcg_wasm_out_brcond(TCGContext *s, TCGType type,
     tcg_wasm_out_br_to_label(s, l, true);
 }
 
+#define CTX_OFFSET(f) offsetof(struct WasmContext, f)
+
+static intptr_t tcg_wasm_out_get_ctx(TCGContext *s, intptr_t off)
+{
+    tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, CTX_IDX);
+    return tcg_wasm_out_norm_ptr(s, off);
+}
+
+static void tcg_wasm_out_exit_tb(TCGContext *s, uintptr_t arg)
+{
+    intptr_t ofs;
+
+    /* Store ctx.tb_ptr = 0 which indicates there is no next TB */
+    ofs = tcg_wasm_out_get_ctx(s, CTX_OFFSET(tb_ptr));
+    tcg_wasm_out_op_const(s, OPC_I64_CONST, 0);
+    tcg_wasm_out_op_ldst(s, OPC_I64_STORE, 0, ofs);
+
+    /* Return the control to the caller */
+    tcg_wasm_out_op_const(s, OPC_I64_CONST, arg);
+    tcg_wasm_out_op(s, OPC_RETURN);
+}
+
+static void tcg_wasm_out_goto(TCGContext *s, TCGReg target, int block_depth)
+{
+    intptr_t ofs;
+
+    /* Check if the target TB is the same as the current TB */
+    tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(target));
+    ofs = tcg_wasm_out_get_ctx(s, CTX_OFFSET(tb_ptr));
+    tcg_wasm_out_op_ldst(s, OPC_I64_LOAD, 0, ofs);
+    tcg_wasm_out_op(s, OPC_I64_EQ);
+
+    /*
+     * If the target TB is the same as the current TB, no need to return to the
+     * caller. Just branch to the top of the current TB.
+     */
+    tcg_wasm_out_op_block(s, OPC_IF, BLOCK_NORET);
+    tcg_wasm_out_op_const(s, OPC_I64_CONST, 0);
+    tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, BLOCK_IDX);
+    tcg_wasm_out_op_idx(s, OPC_BR, block_depth); /* br to the top of loop */
+    tcg_wasm_out_op(s, OPC_END);
+
+    /* Store the target TB to ctx.tb_ptr and return */
+    ofs = tcg_wasm_out_get_ctx(s, CTX_OFFSET(tb_ptr));
+    tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(target));
+    tcg_wasm_out_op_ldst(s, OPC_I64_STORE, 0, ofs);
+    tcg_wasm_out_op_const(s, OPC_I64_CONST, 0);
+    tcg_wasm_out_op(s, OPC_RETURN);
+}
+
+static void tcg_wasm_out_goto_ptr(TCGContext *s, TCGReg arg)
+{
+    tcg_wasm_out_goto(s, arg, 2);
+}
+
+static void tcg_wasm_out_goto_tb(
+    TCGContext *s, int which, uintptr_t cur_reset_ptr)
+{
+    intptr_t ofs;
+
+    /* Set the target TB in the tmp variable. */
+    tcg_wasm_out_op_const(s, OPC_I64_CONST, get_jmp_target_addr(s, which));
+    ofs = tcg_wasm_out_norm_ptr(s, 0);
+    tcg_wasm_out_op_ldst(s, OPC_I64_LOAD, 0, ofs);
+    tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(TCG_REG_TMP));
+
+    /* Goto the target TB if it's registered. */
+    tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(TCG_REG_TMP));
+    tcg_wasm_out_op_const(s, OPC_I64_CONST, cur_reset_ptr);
+    tcg_wasm_out_op(s, OPC_I64_NE);
+    tcg_wasm_out_op_block(s, OPC_IF, BLOCK_NORET);
+    tcg_wasm_out_goto(s, TCG_REG_TMP, 3);
+    tcg_wasm_out_op(s, OPC_END);
+}
+
 static void tcg_out_op_l(TCGContext *s, TCGOpcode op, TCGLabel *l0)
 {
     tcg_insn_unit_tci insn = 0;
@@ -760,6 +841,35 @@ static void tcg_out_op_l(TCGContext *s, TCGOpcode op, TCGLabel *l0)
     tcg_out32(s, insn);
 }
 
+static void tcg_out_op_p(TCGContext *s, TCGOpcode op, void *p0)
+{
+    tcg_insn_unit_tci insn = 0;
+    intptr_t diff;
+
+    /* Special case for exit_tb: map null -> 0. */
+    if (p0 == NULL) {
+        diff = 0;
+    } else {
+        diff = p0 - (void *)(s->code_ptr + 4);
+        tcg_debug_assert(diff != 0);
+        if (diff != sextract32(diff, 0, 20)) {
+            tcg_raise_tb_overflow(s);
+        }
+    }
+    insn = deposit32(insn, 0, 8, op);
+    insn = deposit32(insn, 12, 20, diff);
+    tcg_out32(s, insn);
+}
+
+static void tcg_out_op_r(TCGContext *s, TCGOpcode op, TCGReg r0)
+{
+    tcg_insn_unit_tci insn = 0;
+
+    insn = deposit32(insn, 0, 8, op);
+    insn = deposit32(insn, 8, 4, r0);
+    tcg_out32(s, insn);
+}
+
 static void tcg_out_op_ri(TCGContext *s, TCGOpcode op, TCGReg r0, int32_t i1)
 {
     tcg_insn_unit_tci insn = 0;
@@ -1468,6 +1578,32 @@ static void tcg_out_br(TCGContext *s, TCGLabel *l)
     tcg_wasm_out_br(s, l);
 }
 
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
+{
+    tcg_out_op_p(s, INDEX_op_exit_tb, (void *)arg);
+    tcg_wasm_out_exit_tb(s, arg);
+}
+
+static void tcg_out_goto_tb(TCGContext *s, int which)
+{
+    /* indirect jump method. */
+    tcg_out_op_p(s, INDEX_op_goto_tb, (void *)get_jmp_target_addr(s, which));
+    set_jmp_reset_offset(s, which);
+    tcg_wasm_out_goto_tb(s, which, (intptr_t)s->code_ptr);
+}
+
+static void tcg_out_goto_ptr(TCGContext *s, TCGReg a0)
+{
+    tcg_out_op_r(s, INDEX_op_goto_ptr, a0);
+    tcg_wasm_out_goto_ptr(s, a0);
+}
+
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
+                              uintptr_t jmp_rx, uintptr_t jmp_rw)
+{
+    /* Always indirect, nothing to do */
+}
+
 static void tcg_out_tb_start(TCGContext *s)
 {
     init_sub_buf();
-- 
2.43.0



  parent reply	other threads:[~2025-09-01 11:51 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-01 11:44 [PATCH v3 00/35] wasm: Add Wasm TCG backend based on wasm64 Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 01/35] meson: Add wasm64 support to the --cpu flag Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 02/35] configure: Enable to propagate -sMEMORY64 flag to Emscripten Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 03/35] dockerfiles: Add support for wasm64 to the wasm Dockerfile Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 04/35] .gitlab-ci.d: Add build tests for wasm64 Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 05/35] tcg/wasm: Add tcg-target.h and tcg-target-reg-bits.h Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 06/35] tcg/wasm: Add register-related definitions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 07/35] tcg/wasm: Add constraint definitions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 08/35] tcg/wasm: Add relocation callbacks Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 09/35] tcg/wasm: Add and/or/xor instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 10/35] tcg/wasm: Add add/sub/mul instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 11/35] tcg/wasm: Add shl/shr/sar instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 12/35] tcg/wasm: Add setcond/negsetcond/movcond instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 13/35] tcg/wasm: Add sextract instruction Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 14/35] tcg/wasm: Add load and store instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 15/35] tcg/wasm: Add mov/movi instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 16/35] tcg/wasm: Add ext instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 17/35] tcg/wasm: Add div/rem instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 18/35] tcg/wasm: Add neg/ctpop instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 19/35] tcg/wasm: Add rot/clz/ctz instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 20/35] tcg/wasm: Add br/brcond instructions Kohei Tokunaga
2025-09-01 11:44 ` Kohei Tokunaga [this message]
2025-09-01 11:44 ` [PATCH v3 22/35] tcg/wasm: Add call instruction Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 23/35] tcg/wasm: Add qemu_ld/qemu_st instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 24/35] tcg/wasm: Add mb instruction Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 25/35] tcg/wasm: Mark unimplemented instructions Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 26/35] tcg/wasm: Add initialization of fundamental registers Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 27/35] tcg/wasm: Write wasm binary to TB Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 28/35] tcg/wasm: Implement instantiation of Wasm binary Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 29/35] tcg/wasm: Allow switching coroutine from a helper Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 30/35] tcg/wasm: Enable instantiation of TBs executed many times Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 31/35] tcg/wasm: Enable TLB lookup Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 32/35] tcg/wasm: Add tcg_target_init function Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 33/35] meson.build: enable to build Wasm backend Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 34/35] meson.build: Propagate optimization flag for linking on Emscripten Kohei Tokunaga
2025-09-01 11:44 ` [PATCH v3 35/35] .gitlab-ci.d: build wasm backend in CI Kohei Tokunaga
2025-09-29 22:20 ` [PATCH v3 00/35] wasm: Add Wasm TCG backend based on wasm64 Pierrick Bouvier
2025-09-30  8:26   ` Kohei Tokunaga
2025-10-01 23:08     ` Pierrick Bouvier
2025-10-02  1:33   ` Pierrick Bouvier
2025-10-02 15:59     ` Kohei Tokunaga

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f15853e3bc8c5e6b3a622de90dd14261cb9c82be.1756724464.git.ktokunaga.mail@gmail.com \
    --to=ktokunaga.mail@gmail.com \
    --cc=Alistair.Francis@wdc.com \
    --cc=alex.bennee@linaro.org \
    --cc=arikalo@gmail.com \
    --cc=aurelien@aurel32.net \
    --cc=berrange@redhat.com \
    --cc=chenhuacai@kernel.org \
    --cc=git@xen0n.name \
    --cc=jiaxun.yang@flygoat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=palmer@dabbelt.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@linaro.org \
    --cc=pierrick.bouvier@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=stefanha@redhat.com \
    --cc=sw@weilnetz.de \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).