From 77c66d49e3306a7420d92cfe6e568abe11f56f22 Mon Sep 17 00:00:00 2001 From: James Marsh Date: Tue, 1 Oct 2024 11:40:16 +0100 Subject: [PATCH] Add V128 comparison operations Tested using ``` (module (import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32))) (memory (export "memory") 1) (func $assert_true (param v128) local.get 0 v128.any_true i32.eqz if unreachable end ) (func $main (export "_start") ;; Test v128.not v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 v128.not v128.const i8x16 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 i8x16.eq call $assert_true ;; Test v128.and v128.const i8x16 255 255 255 255 0 0 0 0 255 255 255 255 0 0 0 0 v128.const i8x16 255 255 0 0 255 255 0 0 255 255 0 0 255 255 0 0 v128.and v128.const i8x16 255 255 0 0 0 0 0 0 255 255 0 0 0 0 0 0 i8x16.eq call $assert_true ;; Test v128.andnot v128.const i8x16 255 255 255 255 0 0 0 0 255 255 255 255 0 0 0 0 v128.const i8x16 255 255 0 0 255 255 0 0 255 255 0 0 255 255 0 0 v128.andnot v128.const i8x16 0 0 255 255 0 0 0 0 0 0 255 255 0 0 0 0 i8x16.eq call $assert_true ;; Test v128.or v128.const i8x16 255 255 0 0 0 0 255 255 255 255 0 0 0 0 255 0 v128.const i8x16 0 0 255 255 255 255 0 0 0 0 255 255 255 255 0 0 v128.or v128.const i8x16 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 0 i8x16.eq call $assert_true ;; Test v128.xor v128.const i8x16 255 255 0 0 255 255 0 0 255 255 0 0 255 255 0 0 v128.const i8x16 255 255 255 255 0 0 0 0 255 255 255 255 0 0 0 0 v128.xor v128.const i8x16 0 0 255 255 255 255 0 0 0 0 255 255 255 255 0 0 i8x16.eq call $assert_true i32.const 0 call $proc_exit ) ) ``` --- core/iwasm/common/wasm_loader_common.c | 3 +- core/iwasm/interpreter/wasm_interp_fast.c | 78 ++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/core/iwasm/common/wasm_loader_common.c b/core/iwasm/common/wasm_loader_common.c index 6dd31be2c3..4a9d8a57b2 100644 --- a/core/iwasm/common/wasm_loader_common.c +++ b/core/iwasm/common/wasm_loader_common.c @@ -89,7 +89,8 @@ is_valid_value_type(uint8 type) bool is_valid_value_type_for_interpreter(uint8 value_type) { -#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) +#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \ + && (WASM_ENABLE_FAST_INTERP == 0) /* * Note: regardless of WASM_ENABLE_SIMD, our interpreters don't have * SIMD implemented. It's safer to reject v128, especially for the diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 5ac85127a1..c56acdec1a 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -487,6 +487,8 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame) #define POP_F64() (GET_F64_FROM_ADDR(frame_lp + GET_OFFSET())) +#define POP_V128() (GET_V128_FROM_ADDR(frame_lp + GET_OFFSET())) + #define POP_REF() \ (opnd_off = GET_OFFSET(), CLEAR_FRAME_REF((unsigned)(opnd_off)), \ GET_REF_FROM_ADDR(frame_lp + opnd_off)) @@ -5720,6 +5722,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, /* i8x16 comparison operations */ case SIMD_i8x16_eq: + { + V128 v1 = POP_V128(); + V128 v2 = POP_V128(); + int i; + addr_ret = GET_OFFSET(); + + V128 result; + for (i = 0; i < 16; i++) { + result.i8x16[i] = + v1.i8x16[i] == v2.i8x16[i] ? 0xff : 0; + } + PUT_V128_TO_ADDR(frame_lp + addr_ret, result); + break; + } case SIMD_i8x16_ne: case SIMD_i8x16_lt_s: case SIMD_i8x16_lt_u: @@ -5790,12 +5806,56 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, break; } - /* v128 comparison operations */ + /* v128 bitwise operations */ +#define SIMD_V128_BITWISE_OP_COMMON(result_expr_0, result_expr_1) \ + do { \ + V128 result; \ + result.i64x2[0] = (result_expr_0); \ + result.i64x2[1] = (result_expr_1); \ + addr_ret = GET_OFFSET(); \ + PUT_V128_TO_ADDR(frame_lp + addr_ret, result); \ + } while (0) + case SIMD_v128_not: + { + V128 value = POP_V128(); + SIMD_V128_BITWISE_OP_COMMON(~value.i64x2[0], + ~value.i64x2[1]); + break; + } case SIMD_v128_and: + { + V128 v2 = POP_V128(); + V128 v1 = POP_V128(); + SIMD_V128_BITWISE_OP_COMMON(v1.i64x2[0] & v2.i64x2[0], + v1.i64x2[1] & v2.i64x2[1]); + break; + } case SIMD_v128_andnot: + { + V128 v2 = POP_V128(); + V128 v1 = POP_V128(); + SIMD_V128_BITWISE_OP_COMMON( + v1.i64x2[0] & (~v2.i64x2[0]), + v1.i64x2[1] & (~v2.i64x2[1])); + break; + } case SIMD_v128_or: + { + V128 v2 = POP_V128(); + V128 v1 = POP_V128(); + SIMD_V128_BITWISE_OP_COMMON(v1.i64x2[0] | v2.i64x2[0], + v1.i64x2[1] | v2.i64x2[1]); + break; + } case SIMD_v128_xor: + { + V128 v2 = POP_V128(); + V128 v1 = POP_V128(); + SIMD_V128_BITWISE_OP_COMMON(v1.i64x2[0] ^ v2.i64x2[0], + v1.i64x2[1] ^ v2.i64x2[1]); + break; + } case SIMD_v128_bitselect: { wasm_set_exception(module, "unsupported SIMD opcode"); @@ -5840,6 +5900,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case SIMD_i8x16_neg: case SIMD_i8x16_popcnt: case SIMD_i8x16_all_true: + { + V128 v = POP_V128(); + uint8_t *bytes = (uint8_t *)&v; + bool all_true = true; + + for (int i = 0; i < 16; i++) { + if (bytes[i] == 0) { + all_true = false; + break; + } + } + + PUSH_I32(all_true ? 1 : 0); + break; + } + case SIMD_i8x16_bitmask: case SIMD_i8x16_narrow_i16x8_s: case SIMD_i8x16_narrow_i16x8_u: