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.m...@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