This commit implements rot, clz and ctz operations using Wasm instructions.
Signed-off-by: Kohei Tokunaga <ktokunaga.m...@gmail.com> --- tcg/wasm/tcg-target.c.inc | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tcg/wasm/tcg-target.c.inc b/tcg/wasm/tcg-target.c.inc index 0ba16e8dce..74f3177753 100644 --- a/tcg/wasm/tcg-target.c.inc +++ b/tcg/wasm/tcg-target.c.inc @@ -146,6 +146,7 @@ typedef enum { OPC_I32_CONST = 0x41, OPC_I64_CONST = 0x42, + OPC_I32_EQZ = 0x45, OPC_I32_EQ = 0x46, OPC_I32_NE = 0x47, OPC_I32_LT_S = 0x48, @@ -157,6 +158,7 @@ typedef enum { OPC_I32_GE_S = 0x4e, OPC_I32_GE_U = 0x4f, + OPC_I64_EQZ = 0x50, OPC_I64_EQ = 0x51, OPC_I64_NE = 0x52, OPC_I64_LT_S = 0x53, @@ -168,6 +170,8 @@ typedef enum { OPC_I64_GE_S = 0x59, OPC_I64_GE_U = 0x5a, + OPC_I32_CLZ = 0x67, + OPC_I32_CTZ = 0x68, OPC_I32_ADD = 0x6a, OPC_I32_DIV_S = 0x6d, OPC_I32_DIV_U = 0x6e, @@ -178,8 +182,11 @@ typedef enum { OPC_I32_SHL = 0x74, OPC_I32_SHR_S = 0x75, OPC_I32_SHR_U = 0x76, + OPC_I32_ROTL = 0x77, OPC_I32_ROTR = 0x78, + OPC_I64_CLZ = 0x79, + OPC_I64_CTZ = 0x7a, OPC_I64_POPCNT = 0x7b, OPC_I64_ADD = 0x7c, OPC_I64_SUB = 0x7d, @@ -194,6 +201,7 @@ typedef enum { OPC_I64_SHL = 0x86, OPC_I64_SHR_S = 0x87, OPC_I64_SHR_U = 0x88, + OPC_I64_ROTL = 0x89, OPC_I64_ROTR = 0x8a, OPC_I32_WRAP_I64 = 0xa7, @@ -720,6 +728,42 @@ static void tcg_wasm_out_bswap16( tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(dest)); } +static void tcg_wasm_out_cz( + TCGContext *s, TCGType type, WasmInsn opc32, WasmInsn opc64, + TCGReg ret, TCGReg arg1, TCGReg arg2) +{ + switch (type) { + case TCG_TYPE_I32: + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg1)); + tcg_wasm_out_op(s, OPC_I32_WRAP_I64); + tcg_wasm_out_op(s, OPC_I32_EQZ); + tcg_wasm_out_op_block(s, OPC_IF, BLOCK_I32); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg2)); + tcg_wasm_out_op(s, OPC_I32_WRAP_I64); + tcg_wasm_out_op(s, OPC_ELSE); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg1)); + tcg_wasm_out_op(s, OPC_I32_WRAP_I64); + tcg_wasm_out_op(s, opc32); + tcg_wasm_out_op(s, OPC_END); + tcg_wasm_out_op(s, OPC_I64_EXTEND_I32_U); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); + break; + case TCG_TYPE_I64: + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg1)); + tcg_wasm_out_op(s, OPC_I64_EQZ); + tcg_wasm_out_op_block(s, OPC_IF, BLOCK_I64); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg2)); + tcg_wasm_out_op(s, OPC_ELSE); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg1)); + tcg_wasm_out_op(s, opc64); + tcg_wasm_out_op(s, OPC_END); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); + break; + default: + g_assert_not_reached(); + } +} + static void tcg_wasm_out_mov(TCGContext *s, TCGReg ret, TCGReg arg) { tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg)); @@ -1266,6 +1310,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_cz(s, type, OPC_I32_CLZ, OPC_I64_CLZ, a0, a1, a2); } static const TCGOutOpBinary outop_clz = { @@ -1280,6 +1325,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_cz(s, type, OPC_I32_CTZ, OPC_I64_CTZ, a0, a1, a2); } static const TCGOutOpBinary outop_ctz = { @@ -1496,6 +1542,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_o1_i2_type(s, type, OPC_I32_ROTL, OPC_I64_ROTL, a0, a1, a2); } static const TCGOutOpBinary outop_rotl = { @@ -1510,6 +1557,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_o1_i2_type(s, type, OPC_I32_ROTR, OPC_I64_ROTL, a0, a1, a2); } static const TCGOutOpBinary outop_rotr = { -- 2.43.0