The div and rem operations are implemented using the corresponding
instructions in Wasm. TCI instructions are also generated in the same way as
the original TCI backend.
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
---
tcg/wasm.c | 32 +++++++++++++++++
tcg/wasm/tcg-target-opc.h.inc | 4 +++
tcg/wasm/tcg-target.c.inc | 68 +++++++++++++++++++++++++++++++++++
3 files changed, 104 insertions(+)
V2:
- This commit generates both Wasm and TCI instrucitons.
diff --git a/tcg/wasm.c b/tcg/wasm.c
index 2c8a7b814e..8c8dcb81c7 100644
--- a/tcg/wasm.c
+++ b/tcg/wasm.c
@@ -327,6 +327,38 @@ static uintptr_t tcg_qemu_tb_exec_tci(CPUArchState *env, const void *v_tb_ptr)
ptr = (void *)(regs[r1] + ofs);
*(uint32_t *)ptr = regs[r0];
break;
+ case INDEX_op_divs:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (int64_t)regs[r1] / (int64_t)regs[r2];
+ break;
+ case INDEX_op_divu:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (uint64_t)regs[r1] / (uint64_t)regs[r2];
+ break;
+ case INDEX_op_rems:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (int64_t)regs[r1] % (int64_t)regs[r2];
+ break;
+ case INDEX_op_remu:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (uint64_t)regs[r1] % (uint64_t)regs[r2];
+ break;
+ case INDEX_op_tci_divs32:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (int32_t)regs[r1] / (int32_t)regs[r2];
+ break;
+ case INDEX_op_tci_divu32:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (uint32_t)regs[r1] / (uint32_t)regs[r2];
+ break;
+ case INDEX_op_tci_rems32:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (int32_t)regs[r1] % (int32_t)regs[r2];
+ break;
+ case INDEX_op_tci_remu32:
+ tci_args_rrr(insn, &r0, &r1, &r2);
+ regs[r0] = (uint32_t)regs[r1] % (uint32_t)regs[r2];
+ break;
default:
g_assert_not_reached();
}
diff --git a/tcg/wasm/tcg-target-opc.h.inc b/tcg/wasm/tcg-target-opc.h.inc
index 122b45749a..5ed8c67535 100644
--- a/tcg/wasm/tcg-target-opc.h.inc
+++ b/tcg/wasm/tcg-target-opc.h.inc
@@ -8,3 +8,7 @@ DEF(tci_movi, 1, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(tci_movl, 1, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(tci_setcond32, 1, 2, 1, TCG_OPF_NOT_PRESENT)
DEF(tci_movcond32, 1, 2, 1, TCG_OPF_NOT_PRESENT)
+DEF(tci_divs32, 1, 2, 0, TCG_OPF_NOT_PRESENT)
+DEF(tci_divu32, 1, 2, 0, TCG_OPF_NOT_PRESENT)
+DEF(tci_rems32, 1, 2, 0, TCG_OPF_NOT_PRESENT)
+DEF(tci_remu32, 1, 2, 0, TCG_OPF_NOT_PRESENT)
diff --git a/tcg/wasm/tcg-target.c.inc b/tcg/wasm/tcg-target.c.inc
index e41b3a0c27..38459a60d6 100644
--- a/tcg/wasm/tcg-target.c.inc
+++ b/tcg/wasm/tcg-target.c.inc
@@ -181,12 +181,20 @@ typedef enum {
OPC_I64_GE_U = 0x5a,
OPC_I32_ADD = 0x6a,
+ OPC_I32_DIV_S = 0x6d,
+ OPC_I32_DIV_U = 0x6e,
+ OPC_I32_REM_S = 0x6f,
+ OPC_I32_REM_U = 0x70,
OPC_I32_SHR_S = 0x75,
OPC_I32_SHR_U = 0x76,
OPC_I64_ADD = 0x7c,
OPC_I64_SUB = 0x7d,
OPC_I64_MUL = 0x7e,
+ OPC_I64_DIV_S = 0x7f,
+ OPC_I64_DIV_U = 0x80,
+ OPC_I64_REM_S = 0x81,
+ OPC_I64_REM_U = 0x82,
OPC_I64_AND = 0x83,
OPC_I64_OR = 0x84,
OPC_I64_XOR = 0x85,
@@ -1070,6 +1078,66 @@ static const TCGOutOpUnary outop_extrh_i64_i32 = {
.out_rr = tgen_extrh_i64_i32,
};
+static void tgen_divs(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ TCGOpcode opc = (type == TCG_TYPE_I32
+ ? INDEX_op_tci_divs32
+ : INDEX_op_divs);
+ tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_o1_i2_type(s, type, OPC_I32_DIV_S, OPC_I64_DIV_S, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_divs = {
+ .base.static_constraint = C_O1_I2(r, r, r),
+ .out_rrr = tgen_divs,
+};
+
+static void tgen_divu(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ TCGOpcode opc = (type == TCG_TYPE_I32
+ ? INDEX_op_tci_divu32
+ : INDEX_op_divu);
+ tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_o1_i2_type(s, type, OPC_I32_DIV_U, OPC_I64_DIV_U, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_divu = {
+ .base.static_constraint = C_O1_I2(r, r, r),
+ .out_rrr = tgen_divu,
+};
+
+static void tgen_rems(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ TCGOpcode opc = (type == TCG_TYPE_I32
+ ? INDEX_op_tci_rems32
+ : INDEX_op_rems);
+ tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_o1_i2_type(s, type, OPC_I32_REM_S, OPC_I64_REM_S, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_rems = {
+ .base.static_constraint = C_O1_I2(r, r, r),
+ .out_rrr = tgen_rems,
+};
+
+static void tgen_remu(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ TCGOpcode opc = (type == TCG_TYPE_I32
+ ? INDEX_op_tci_remu32
+ : INDEX_op_remu);
+ tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_o1_i2_type(s, type, OPC_I32_REM_U, OPC_I64_REM_U, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_remu = {
+ .base.static_constraint = C_O1_I2(r, r, r),
+ .out_rrr = tgen_remu,
+};
+
static void tcg_out_tb_start(TCGContext *s)
{
init_sub_buf();
--
2.43.0