summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/literal.h6
-rw-r--r--src/wasm-interpreter.h8
-rw-r--r--src/wasm/literal.cpp48
-rw-r--r--test/spec/simd.wast23
4 files changed, 83 insertions, 2 deletions
diff --git a/src/literal.h b/src/literal.h
index 746fa5d3e..f7ce78f7a 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -636,6 +636,12 @@ public:
Literal extendHighSToI64x2() const;
Literal extendLowUToI64x2() const;
Literal extendHighUToI64x2() const;
+ Literal convertLowSToF64x2() const;
+ Literal convertLowUToF64x2() const;
+ Literal truncSatZeroSToI32x4() const;
+ Literal truncSatZeroUToI32x4() const;
+ Literal demoteZeroToF32x4() const;
+ Literal promoteLowToF64x2() const;
Literal swizzleI8x16(const Literal& other) const;
// Checks if an RTT value is a sub-rtt of another, that is, whether GC data
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index a846edf97..77e432436 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -399,7 +399,6 @@ public:
return value.extendS16();
case ExtendS32Int64:
return value.extendS32();
-
case NegFloat32:
case NegFloat64:
return value.neg();
@@ -570,12 +569,17 @@ public:
case ExtendHighUVecI32x4ToVecI64x2:
return value.extendHighUToI64x2();
case ConvertLowSVecI32x4ToVecF64x2:
+ return value.convertLowSToF64x2();
case ConvertLowUVecI32x4ToVecF64x2:
+ return value.convertLowUToF64x2();
case TruncSatZeroSVecF64x2ToVecI32x4:
+ return value.truncSatZeroSToI32x4();
case TruncSatZeroUVecF64x2ToVecI32x4:
+ return value.truncSatZeroUToI32x4();
case DemoteZeroVecF64x2ToVecF32x4:
+ return value.demoteZeroToF32x4();
case PromoteLowVecF32x4ToVecF64x2:
- WASM_UNREACHABLE("unimp");
+ return value.promoteLowToF64x2();
case InvalidUnary:
WASM_UNREACHABLE("invalid unary op");
}
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index b6618219d..c7a9ca844 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -2388,6 +2388,16 @@ Literal extend(const Literal& vec) {
return Literal(result);
}
+template<LaneOrder Side> Literal extendF32(const Literal& vec) {
+ LaneArray<4> lanes = vec.getLanesF32x4();
+ LaneArray<2> result;
+ for (size_t i = 0; i < 2; ++i) {
+ size_t idx = (Side == LaneOrder::Low) ? i : i + 2;
+ result[i] = Literal((double)lanes[idx].getf32());
+ }
+ return Literal(result);
+}
+
Literal Literal::extendLowSToI16x8() const {
return extend<8, int8_t, int16_t, LaneOrder::Low>(*this);
}
@@ -2475,6 +2485,44 @@ Literal Literal::extMulHighUI64x2(const Literal& other) const {
return extMul<2, uint32_t, uint64_t, LaneOrder::High>(*this, other);
}
+Literal Literal::convertLowSToF64x2() const {
+ return extend<2, int32_t, double, LaneOrder::Low>(*this);
+}
+Literal Literal::convertLowUToF64x2() const {
+ return extend<2, uint32_t, double, LaneOrder::Low>(*this);
+}
+
+template<int Lanes,
+ LaneArray<Lanes / 2> (Literal::*IntoLanes)() const,
+ Literal (Literal::*UnaryOp)(void) const>
+static Literal unary_zero(const Literal& val) {
+ LaneArray<Lanes / 2> lanes = (val.*IntoLanes)();
+ LaneArray<Lanes> result;
+ for (size_t i = 0; i < Lanes / 2; ++i) {
+ result[i] = (lanes[i].*UnaryOp)();
+ }
+ for (size_t i = Lanes / 2; i < Lanes; ++i) {
+ result[i] = Literal::makeZero(lanes[0].type);
+ }
+ return Literal(result);
+}
+
+Literal Literal::truncSatZeroSToI32x4() const {
+ return unary_zero<4, &Literal::getLanesF64x2, &Literal::truncSatToSI32>(
+ *this);
+}
+Literal Literal::truncSatZeroUToI32x4() const {
+ return unary_zero<4, &Literal::getLanesF64x2, &Literal::truncSatToUI32>(
+ *this);
+}
+
+Literal Literal::demoteZeroToF32x4() const {
+ return unary_zero<4, &Literal::getLanesF64x2, &Literal::demote>(*this);
+}
+Literal Literal::promoteLowToF64x2() const {
+ return extendF32<LaneOrder::Low>(*this);
+}
+
Literal Literal::swizzleI8x16(const Literal& other) const {
auto lanes = getLanesUI8x16();
auto indices = other.getLanesUI8x16();
diff --git a/test/spec/simd.wast b/test/spec/simd.wast
index d246cfdd0..cec571387 100644
--- a/test/spec/simd.wast
+++ b/test/spec/simd.wast
@@ -254,6 +254,12 @@
(func (export "v128.load32_zero") (param $0 i32) (result v128) (v128.load32_zero (local.get $0)))
(func (export "v128.load64_zero") (param $0 i32) (result v128) (v128.load64_zero (local.get $0)))
(func (export "i8x16.swizzle") (param $0 v128) (param $1 v128) (result v128) (i8x16.swizzle (local.get $0) (local.get $1)))
+ (func (export "f64x2.convert_low_i32x4_s") (param $0 v128) (result v128) (f64x2.convert_low_i32x4_s (local.get $0)))
+ (func (export "f64x2.convert_low_i32x4_u") (param $0 v128) (result v128) (f64x2.convert_low_i32x4_u (local.get $0)))
+ (func (export "i32x4.trunc_sat_f64x2_s_zero") (param $0 v128) (result v128) (i32x4.trunc_sat_f64x2_s_zero (local.get $0)))
+ (func (export "i32x4.trunc_sat_f64x2_u_zero") (param $0 v128) (result v128) (i32x4.trunc_sat_f64x2_u_zero (local.get $0)))
+ (func (export "f32x4.demote_f64x2_zero") (param $0 v128) (result v128) (f32x4.demote_f64x2_zero (local.get $0)))
+ (func (export "f64x2.promote_low_f32x4") (param $0 v128) (result v128) (f64x2.promote_low_f32x4 (local.get $0)))
)
;; TODO: Additional f64x2 conversions if specified
@@ -1123,3 +1129,20 @@
)
(v128.const i8x16 0xf0 0xf4 0xf8 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0xff 0xfd 0xfc 0xf8 0xf4 0xf0)
)
+
+(assert_return (invoke "f64x2.convert_low_i32x4_s" (v128.const i32x4 1 -2147483648 0 0)) (v128.const f64x2 1.0 -2147483648))
+(assert_return (invoke "f64x2.convert_low_i32x4_u" (v128.const i32x4 -2147483648 0xffffffff 0 0)) (v128.const f64x2 2147483648 4294967295.0))
+(assert_return (invoke "i32x4.trunc_sat_f64x2_s_zero" (v128.const f64x2 -inf 4294967296.0)) (v128.const i32x4 -2147483648 2147483647 0 0))
+(assert_return (invoke "i32x4.trunc_sat_f64x2_u_zero" (v128.const f64x2 -inf 4294967296.0)) (v128.const i32x4 0 4294967295 0 0))
+(assert_return
+ (invoke "f32x4.demote_f64x2_zero"
+ (v128.const f64x2 0x1.fffffe0000000p-127 -0x1.6972b30cfb562p+1)
+ )
+ (v128.const f32x4 0x1p-126 -0x1.6972b4p+1 0 0)
+)
+(assert_return
+ (invoke "f64x2.promote_low_f32x4"
+ (v128.const f32x4 -0x1p-149 0x1.8f867ep+125 0 0)
+ )
+ (v128.const f64x2 -0x1p-149 6.6382536710104395e+37)
+)