This commit implements rot, clz and ctz operations using Wasm instructions.
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
---
tcg/wasm32/tcg-target.c.inc | 155 ++++++++++++++++++++++++++++++++++++
1 file changed, 155 insertions(+)
diff --git a/tcg/wasm32/tcg-target.c.inc b/tcg/wasm32/tcg-target.c.inc
index e5de2f69bd..75e47f8c8c 100644
--- a/tcg/wasm32/tcg-target.c.inc
+++ b/tcg/wasm32/tcg-target.c.inc
@@ -200,6 +200,14 @@ static void tcg_wasm_out_op_i64_xor(TCGContext *s)
{
tcg_wasm_out8(s, 0x85);
}
+static void tcg_wasm_out_op_i64_clz(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x79);
+}
+static void tcg_wasm_out_op_i64_ctz(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x7a);
+}
static void tcg_wasm_out_op_i64_popcnt(TCGContext *s)
{
tcg_wasm_out8(s, 0x7b);
@@ -244,6 +252,10 @@ static void tcg_wasm_out_op_i64_shr_u(TCGContext *s)
{
tcg_wasm_out8(s, 0x88);
}
+static void tcg_wasm_out_op_i64_rotl(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x89);
+}
static void tcg_wasm_out_op_i64_rotr(TCGContext *s)
{
tcg_wasm_out8(s, 0x8a);
@@ -268,6 +280,14 @@ static void tcg_wasm_out_op_i64_extend16_s(TCGContext *s)
{
tcg_wasm_out8(s, 0xc3);
}
+static void tcg_wasm_out_op_i32_clz(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x67);
+}
+static void tcg_wasm_out_op_i32_ctz(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x68);
+}
static void tcg_wasm_out_op_i32_add(TCGContext *s)
{
tcg_wasm_out8(s, 0x6a);
@@ -292,16 +312,33 @@ static void tcg_wasm_out_op_i32_shr_u(TCGContext *s)
{
tcg_wasm_out8(s, 0x76);
}
+static void tcg_wasm_out_op_i32_rotl(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x77);
+}
static void tcg_wasm_out_op_i32_rotr(TCGContext *s)
{
tcg_wasm_out8(s, 0x78);
}
+static void tcg_wasm_out_op_i32_eqz(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x45);
+}
+static void tcg_wasm_out_op_i64_eqz(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x50);
+}
static void tcg_wasm_out_op_if_ret_i64(TCGContext *s)
{
tcg_wasm_out8(s, 0x04);
tcg_wasm_out8(s, 0x7e);
}
+static void tcg_wasm_out_op_if_ret_i32(TCGContext *s)
+{
+ tcg_wasm_out8(s, 0x04);
+ tcg_wasm_out8(s, 0x7f);
+}
static void tcg_wasm_out_op_else(TCGContext *s)
{
tcg_wasm_out8(s, 0x05);
@@ -360,6 +397,8 @@ tcg_wasm_out_i64_calc(xor);
tcg_wasm_out_i64_calc(add);
tcg_wasm_out_i64_calc(sub);
tcg_wasm_out_i64_calc(mul);
+tcg_wasm_out_i64_calc(rotl);
+tcg_wasm_out_i64_calc(rotr);
static const struct {
uint8_t i32;
@@ -918,6 +957,118 @@ static void tcg_wasm_out_bswap16(
tcg_wasm_out_op_global_set_r(s, dest);
}
+static void tcg_wasm_out_rotl(
+ 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_global_get_r(s, arg2);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i32_rotl(s);
+ tcg_wasm_out_op_i64_extend_i32_s(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ case TCG_TYPE_I64:
+ tcg_wasm_out_i64_calc_rotl(s, ret, arg1, arg2);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void tcg_wasm_out_rotr(
+ 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_global_get_r(s, arg2);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i32_rotr(s);
+ tcg_wasm_out_op_i64_extend_i32_s(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ case TCG_TYPE_I64:
+ tcg_wasm_out_i64_calc_rotr(s, ret, arg1, arg2);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void tcg_wasm_out_clz(
+ 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_i32_eqz(s);
+ tcg_wasm_out_op_if_ret_i32(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_else(s);
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i32_clz(s);
+ tcg_wasm_out_op_end(s);
+ tcg_wasm_out_op_i64_extend_i32_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_i64_eqz(s);
+ tcg_wasm_out_op_if_ret_i64(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_else(s);
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i64_clz(s);
+ tcg_wasm_out_op_end(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void tcg_wasm_out_ctz(
+ 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_i32_eqz(s);
+ tcg_wasm_out_op_if_ret_i32(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_else(s);
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i32_wrap_i64(s);
+ tcg_wasm_out_op_i32_ctz(s);
+ tcg_wasm_out_op_end(s);
+ tcg_wasm_out_op_i64_extend_i32_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_i64_eqz(s);
+ tcg_wasm_out_op_if_ret_i64(s);
+ tcg_wasm_out_op_global_get_r(s, arg2);
+ tcg_wasm_out_op_else(s);
+ tcg_wasm_out_op_global_get_r(s, arg1);
+ tcg_wasm_out_op_i64_ctz(s);
+ tcg_wasm_out_op_end(s);
+ tcg_wasm_out_op_global_set_r(s, ret);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
static void tcg_wasm_out_ld(
TCGContext *s, TCGType type, TCGReg val, TCGReg base, intptr_t offset)
{
@@ -1710,6 +1861,7 @@ static void tgen_clz(TCGContext *s, TCGType type,
? INDEX_op_tci_clz32
: INDEX_op_clz);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_clz(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_clz = {
@@ -1724,6 +1876,7 @@ static void tgen_ctz(TCGContext *s, TCGType type,
? INDEX_op_tci_ctz32
: INDEX_op_ctz);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_ctz(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_ctz = {
@@ -1948,6 +2101,7 @@ static void tgen_rotl(TCGContext *s, TCGType type,
? INDEX_op_tci_rotl32
: INDEX_op_rotl);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_rotl(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_rotl = {
@@ -1962,6 +2116,7 @@ static void tgen_rotr(TCGContext *s, TCGType type,
? INDEX_op_tci_rotr32
: INDEX_op_rotr);
tcg_out_op_rrr(s, opc, a0, a1, a2);
+ tcg_wasm_out_rotr(s, type, a0, a1, a2);
}
static const TCGOutOpBinary outop_rotr = {
--
2.43.0