This commit implements rem and div operations using Wasm's rem/div
instructions.
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
---
tcg/wasm32/tcg-target.c.inc | 120 ++++++++++++++++++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/tcg/wasm32/tcg-target.c.inc b/tcg/wasm32/tcg-target.c.inc
index 1a6069e288..66d3977d31 100644
--- a/tcg/wasm32/tcg-target.c.inc
+++ b/tcg/wasm32/tcg-target.c.inc
@@ -212,6 +212,22 @@ static void tcg_wasm_out_op_i64_mul(TCGContext *s)
{
tcg_wasm_out8(s, 0x7e);
}
+static void tcg_wasm_out_op_i64_div_s(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x7f);
+}
+static void tcg_wasm_out_op_i64_div_u(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x80);
+}
+static void tcg_wasm_out_op_i64_rem_s(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x81);
+}
+static void tcg_wasm_out_op_i64_rem_u(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x82);
+}
static void tcg_wasm_out_op_i64_shl(TCGContext *s)
{
tcg_wasm_out8(s, 0x86);
@@ -995,6 +1011,106 @@ static void tcg_wasm_out_movi(TCGContext *s, TCGType type,
tcg_wasm_out_op_global_set_r(s, ret);
}
+static void tcg_wasm_out_rem_s(
+ TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, TCGReg arg2)
+{
+ switch (type) {
+ case TCG_TYPE_I32:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i64_extend_i32_s(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i64_extend_i32_s(s);
+ tcg_wasm_out_op_i64_rem_s(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ case TCG_TYPE_I64:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i64_rem_s(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void tcg_wasm_out_rem_u(
+ TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, TCGReg arg2)
+{
+ switch (type) {
+ case TCG_TYPE_I32:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i64_const(s, 0xffffffff);
+ tcg_wasm_out_op_i64_and(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i64_const(s, 0xffffffff);
+ tcg_wasm_out_op_i64_and(s);
+ tcg_wasm_out_op_i64_rem_u(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ case TCG_TYPE_I64:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i64_rem_u(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void tcg_wasm_out_div_s(
+ TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, TCGReg arg2)
+{
+ switch (type) {
+ case TCG_TYPE_I32:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i64_extend_i32_s(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i64_extend_i32_s(s);
+ tcg_wasm_out_op_i64_div_s(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ case TCG_TYPE_I64:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i64_div_s(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void tcg_wasm_out_div_u(
+ TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, TCGReg arg2)
+{
+ switch (type) {
+ case TCG_TYPE_I32:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i64_const(s, 0xffffffff);
+ tcg_wasm_out_op_i64_and(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i64_const(s, 0xffffffff);
+ tcg_wasm_out_op_i64_and(s);
+ tcg_wasm_out_op_i64_div_u(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ case TCG_TYPE_I64:
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i64_div_u(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
static bool patch_reloc(tcg_insn_unit *code_ptr_i, int type,
intptr_t value, intptr_t addend)
{
@@ -1556,6 +1672,7 @@ static void tgen_divs(TCGContext *s, TCGType type,
? INDEX_op_tci_divs32
: INDEX_op_divs);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_div_s(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_divs = {
@@ -1574,6 +1691,7 @@ static void tgen_divu(TCGContext *s, TCGType type,
? INDEX_op_tci_divu32
: INDEX_op_divu);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_div_u(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_divu = {
@@ -1718,6 +1836,7 @@ static void tgen_rems(TCGContext *s, TCGType type,
? INDEX_op_tci_rems32
: INDEX_op_rems);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_rem_s(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_rems = {
@@ -1732,6 +1851,7 @@ static void tgen_remu(TCGContext *s, TCGType type,
? INDEX_op_tci_remu32
: INDEX_op_remu);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_rem_u(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_remu = {
--
2.43.0