This commit introduces Wasm module local variables[1] assigned from the index 0. These variables are used as temporary storage during calculations.
[1] https://webassembly.github.io/spec/core/binary/instructions.html#variable-instructions Signed-off-by: Kohei Tokunaga <ktokunaga.m...@gmail.com> --- tcg/wasm/tcg-target.c.inc | 117 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/tcg/wasm/tcg-target.c.inc b/tcg/wasm/tcg-target.c.inc index afaea76d5c..7f4ec250ff 100644 --- a/tcg/wasm/tcg-target.c.inc +++ b/tcg/wasm/tcg-target.c.inc @@ -116,10 +116,16 @@ static const uint8_t tcg_target_reg_index[TCG_TARGET_NB_REGS] = { #define REG_IDX(r) tcg_target_reg_index[r] +/* Temporary local variables */ +#define TMP32_LOCAL_0_IDX 0 +#define TMP64_LOCAL_0_IDX 1 + typedef enum { OPC_IF = 0x04, OPC_ELSE = 0x05, OPC_END = 0x0b, + OPC_LOCAL_GET = 0x20, + OPC_LOCAL_SET = 0x21, OPC_GLOBAL_GET = 0x23, OPC_GLOBAL_SET = 0x24, @@ -163,9 +169,12 @@ typedef enum { OPC_I64_GE_U = 0x5a, OPC_I32_ADD = 0x6a, + OPC_I32_AND = 0x71, + OPC_I32_OR = 0x72, OPC_I32_SHL = 0x74, OPC_I32_SHR_S = 0x75, OPC_I32_SHR_U = 0x76, + OPC_I32_ROTR = 0x78, OPC_I64_ADD = 0x7c, OPC_I64_SUB = 0x7d, @@ -176,6 +185,7 @@ typedef enum { OPC_I64_SHL = 0x86, OPC_I64_SHR_S = 0x87, OPC_I64_SHR_U = 0x88, + OPC_I64_ROTR = 0x8a, OPC_I32_WRAP_I64 = 0xa7, OPC_I64_EXTEND_I32_S = 0xac, @@ -524,6 +534,110 @@ 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_bswap64( + TCGContext *s, TCGReg dest, TCGReg src) +{ + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(src)); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 32); + tcg_wasm_out_op(s, OPC_I64_ROTR); + tcg_wasm_out_op_idx(s, OPC_LOCAL_SET, TMP64_LOCAL_0_IDX); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP64_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 0xff000000ff000000); + tcg_wasm_out_op(s, OPC_I64_AND); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 24); + tcg_wasm_out_op(s, OPC_I64_SHR_U); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP64_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 0x00ff000000ff0000); + tcg_wasm_out_op(s, OPC_I64_AND); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 8); + tcg_wasm_out_op(s, OPC_I64_SHR_U); + + tcg_wasm_out_op(s, OPC_I64_OR); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP64_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 0x0000ff000000ff00); + tcg_wasm_out_op(s, OPC_I64_AND); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 8); + tcg_wasm_out_op(s, OPC_I64_SHL); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP64_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 0x000000ff000000ff); + tcg_wasm_out_op(s, OPC_I64_AND); + tcg_wasm_out_op_const(s, OPC_I64_CONST, 24); + tcg_wasm_out_op(s, OPC_I64_SHL); + + tcg_wasm_out_op(s, OPC_I64_OR); + + tcg_wasm_out_op(s, OPC_I64_OR); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(dest)); +} + +static void tcg_wasm_out_bswap32( + TCGContext *s, TCGReg dest, TCGReg src, int flags) +{ + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(src)); + tcg_wasm_out_op(s, OPC_I32_WRAP_I64); + tcg_wasm_out_op_idx(s, OPC_LOCAL_SET, TMP32_LOCAL_0_IDX); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP32_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 16); + tcg_wasm_out_op(s, OPC_I32_ROTR); + tcg_wasm_out_op_idx(s, OPC_LOCAL_SET, TMP32_LOCAL_0_IDX); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP32_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 0xff00ff00); + tcg_wasm_out_op(s, OPC_I32_AND); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 8); + tcg_wasm_out_op(s, OPC_I32_SHR_U); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP32_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 0x00ff00ff); + tcg_wasm_out_op(s, OPC_I32_AND); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 8); + tcg_wasm_out_op(s, OPC_I32_SHL); + + tcg_wasm_out_op(s, OPC_I32_OR); + if (flags & TCG_BSWAP_OS) { + tcg_wasm_out_op(s, OPC_I64_EXTEND_I32_S); + } else { + tcg_wasm_out_op(s, OPC_I64_EXTEND_I32_U); + } + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(dest)); +} + +static void tcg_wasm_out_bswap16( + TCGContext *s, TCGReg dest, TCGReg src, int flags) +{ + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(src)); + tcg_wasm_out_op(s, OPC_I32_WRAP_I64); + tcg_wasm_out_op_idx(s, OPC_LOCAL_SET, TMP32_LOCAL_0_IDX); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP32_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 8); + tcg_wasm_out_op(s, OPC_I32_ROTR); + tcg_wasm_out_op_idx(s, OPC_LOCAL_SET, TMP32_LOCAL_0_IDX); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP32_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 0x000000ff); + tcg_wasm_out_op(s, OPC_I32_AND); + + tcg_wasm_out_op_idx(s, OPC_LOCAL_GET, TMP32_LOCAL_0_IDX); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 0xff000000); + tcg_wasm_out_op(s, OPC_I32_AND); + tcg_wasm_out_op_const(s, OPC_I32_CONST, 16); + if (flags & TCG_BSWAP_OS) { + tcg_wasm_out_op(s, OPC_I32_SHR_S); + } else { + tcg_wasm_out_op(s, OPC_I32_SHR_U); + } + + tcg_wasm_out_op(s, OPC_I32_OR); + tcg_wasm_out_op(s, OPC_I64_EXTEND_I32_U); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(dest)); +} + static void tcg_wasm_out_mov(TCGContext *s, TCGReg ret, TCGReg arg) { tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg)); @@ -1448,6 +1562,7 @@ static void tgen_bswap16(TCGContext *s, TCGType type, if (flags & TCG_BSWAP_OS) { tcg_tci_out_sextract(s, TCG_TYPE_REG, a0, a0, 0, 16); } + tcg_wasm_out_bswap16(s, a0, a1, flags); } static const TCGOutOpBswap outop_bswap16 = { @@ -1462,6 +1577,7 @@ static void tgen_bswap32(TCGContext *s, TCGType type, if (flags & TCG_BSWAP_OS) { tcg_tci_out_sextract(s, TCG_TYPE_REG, a0, a0, 0, 32); } + tcg_wasm_out_bswap32(s, a0, a1, flags); } static const TCGOutOpBswap outop_bswap32 = { @@ -1473,6 +1589,7 @@ static const TCGOutOpBswap outop_bswap32 = { static void tgen_bswap64(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1) { tcg_out_op_rr(s, INDEX_op_bswap64, a0, a1); + tcg_wasm_out_bswap64(s, a0, a1); } static const TCGOutOpUnary outop_bswap64 = { -- 2.43.0