The neg/ctpop operations are implemented using the corresponding instructions in Wasm. TCI instructions are also generated in the same way as the original TCI backend.
The Wasm backend implements only TCG_TARGET_REG_BITS=64 so the ctpop instruction is generated only for 64bit operations, as declared in cset_ctpop. Therefore, this commit adds only the 64bit version of ctpop implementation. Signed-off-by: Kohei Tokunaga <ktokunaga.m...@gmail.com> --- tcg/wasm.c | 4 ++++ tcg/wasm/tcg-target.c.inc | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) V2: - This commit generates both Wasm and TCI instrucitons. - Removed the not operation to rely on default expansion. - Fixed the neg implementation to "ret = 0 - arg" diff --git a/tcg/wasm.c b/tcg/wasm.c index 8c8dcb81c7..a5e72d8fe5 100644 --- a/tcg/wasm.c +++ b/tcg/wasm.c @@ -359,6 +359,10 @@ static uintptr_t tcg_qemu_tb_exec_tci(CPUArchState *env, const void *v_tb_ptr) tci_args_rrr(insn, &r0, &r1, &r2); regs[r0] = (uint32_t)regs[r1] % (uint32_t)regs[r2]; break; + case INDEX_op_ctpop: + tci_args_rr(insn, &r0, &r1); + regs[r0] = ctpop64(regs[r1]); + break; default: g_assert_not_reached(); } diff --git a/tcg/wasm/tcg-target.c.inc b/tcg/wasm/tcg-target.c.inc index 38459a60d6..27f3a7414b 100644 --- a/tcg/wasm/tcg-target.c.inc +++ b/tcg/wasm/tcg-target.c.inc @@ -188,6 +188,7 @@ typedef enum { OPC_I32_SHR_S = 0x75, OPC_I32_SHR_U = 0x76, + OPC_I64_POPCNT = 0x7b, OPC_I64_ADD = 0x7c, OPC_I64_SUB = 0x7d, OPC_I64_MUL = 0x7e, @@ -547,6 +548,21 @@ static void tcg_wasm_out_movi(TCGContext *s, TCGType type, tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); } +static void tcg_wasm_out_neg(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_wasm_out_op_const(s, OPC_I64_CONST, 0); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg)); + tcg_wasm_out_op(s, OPC_I64_SUB); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); +} + +static void tcg_wasm_out_ctpop64(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg)); + tcg_wasm_out_op(s, OPC_I64_POPCNT); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); +} + static void tcg_out_op_ri(TCGContext *s, TCGOpcode op, TCGReg r0, int32_t i1) { tcg_insn_unit_tci insn = 0; @@ -1138,6 +1154,34 @@ static const TCGOutOpBinary outop_remu = { .out_rrr = tgen_remu, }; +static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1) +{ + tcg_out_op_rr(s, INDEX_op_neg, a0, a1); + tcg_wasm_out_neg(s, a0, a1); +} + +static const TCGOutOpUnary outop_neg = { + .base.static_constraint = C_O1_I1(r, r), + .out_rr = tgen_neg, +}; + +static void tgen_ctpop(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1) +{ + tcg_out_op_rr(s, INDEX_op_ctpop, a0, a1); + tcg_wasm_out_ctpop64(s, a0, a1); +} + +static TCGConstraintSetIndex cset_ctpop(TCGType type, unsigned flags) +{ + return type == TCG_TYPE_REG ? C_O1_I1(r, r) : C_NotImplemented; +} + +static const TCGOutOpUnary outop_ctpop = { + .base.static_constraint = C_Dynamic, + .base.dynamic_constraint = cset_ctpop, + .out_rr = tgen_ctpop, +}; + static void tcg_out_tb_start(TCGContext *s) { init_sub_buf(); -- 2.43.0