The ext 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/tcg-target-has.h | 1 + tcg/wasm/tcg-target.c.inc | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) V2: - This commit generates both Wasm and TCI instrucitons. - Moved tcg_wasm_out_extract to this commit for internal use to implement the ext instructions, although the extract operation itself is not generated in the Wasm backend. diff --git a/tcg/wasm/tcg-target-has.h b/tcg/wasm/tcg-target-has.h index cfb85388de..a29ceb2ea5 100644 --- a/tcg/wasm/tcg-target-has.h +++ b/tcg/wasm/tcg-target-has.h @@ -3,6 +3,7 @@ #define TCG_TARGET_HAS_H #define TCG_TARGET_HAS_tst 0 +#define TCG_TARGET_HAS_extr_i64_i32 0 #define TCG_TARGET_extract_valid(type, ofs, len) 0 #define TCG_TARGET_sextract_valid(type, ofs, len) \ diff --git a/tcg/wasm/tcg-target.c.inc b/tcg/wasm/tcg-target.c.inc index def1f5cd5e..e41b3a0c27 100644 --- a/tcg/wasm/tcg-target.c.inc +++ b/tcg/wasm/tcg-target.c.inc @@ -434,6 +434,22 @@ static void tcg_wasm_out_sextract(TCGContext *s, TCGReg dest, TCGReg arg1, tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(dest)); } +static void tcg_wasm_out_extract(TCGContext *s, TCGReg dest, TCGReg arg1, + int pos, int len) +{ + int64_t mask = ~0ULL >> (64 - len); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg1)); + if (pos > 0) { + tcg_wasm_out_op_const(s, OPC_I64_CONST, pos); + tcg_wasm_out_op(s, OPC_I64_SHR_U); + } + if ((pos + len) < 64) { + tcg_wasm_out_op_const(s, OPC_I64_CONST, mask); + tcg_wasm_out_op(s, OPC_I64_AND); + } + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(dest)); +} + /* * The size of the offset field of Wasm's load/store instruction defers * depending on the "-sMEMORY64" flag value: 64bit when "-sMEMORY64=1" @@ -991,6 +1007,69 @@ static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, return false; } +static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) +{ + tcg_out_sextract(s, type, rd, rs, 0, 8); + tcg_wasm_out_sextract(s, rd, rs, 0, 8); +} + +static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs) +{ + tcg_out_op_rrbb(s, INDEX_op_extract, rd, rs, 0, 8); + tcg_wasm_out_extract(s, rd, rs, 0, 8); +} + +static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) +{ + tcg_out_sextract(s, type, rd, rs, 0, 16); + tcg_wasm_out_sextract(s, rd, rs, 0, 16); +} + +static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs) +{ + tcg_out_op_rrbb(s, INDEX_op_extract, rd, rs, 0, 16); + tcg_wasm_out_extract(s, rd, rs, 0, 16); +} + +static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs) +{ + tcg_out_sextract(s, TCG_TYPE_I64, rd, rs, 0, 32); + tcg_wasm_out_sextract(s, rd, rs, 0, 32); +} + +static void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rs) +{ + tcg_out_op_rrbb(s, INDEX_op_extract, rd, rs, 0, 32); + tcg_wasm_out_extract(s, rd, rs, 0, 32); +} + +static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs) +{ + tcg_out_ext32s(s, rd, rs); +} + +static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs) +{ + tcg_out_ext32u(s, rd, rs); +} + +static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs) +{ + tcg_out_op_rr(s, INDEX_op_mov, rd, rs); + tcg_wasm_out_extract(s, rd, rs, 0, 32); +} + +static void tgen_extrh_i64_i32(TCGContext *s, TCGType t, TCGReg a0, TCGReg a1) +{ + tcg_out_op_rrbb(s, INDEX_op_extract, a0, a1, 32, 32); + tcg_wasm_out_extract(s, a0, a1, 32, 32); +} + +static const TCGOutOpUnary outop_extrh_i64_i32 = { + .base.static_constraint = C_O1_I1(r, r), + .out_rr = tgen_extrh_i64_i32, +}; + static void tcg_out_tb_start(TCGContext *s) { init_sub_buf(); -- 2.43.0