summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/literal.h1
-rw-r--r--src/wasm/literal.cpp11
-rw-r--r--test/spec/simd.wast9
3 files changed, 19 insertions, 2 deletions
diff --git a/src/literal.h b/src/literal.h
index 965ec157c..0b1b6fa90 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -644,6 +644,7 @@ private:
Literal subSatUI8(const Literal& other) const;
Literal subSatSI16(const Literal& other) const;
Literal subSatUI16(const Literal& other) const;
+ Literal q15MulrSatSI16(const Literal& other) const;
Literal minInt(const Literal& other) const;
Literal maxInt(const Literal& other) const;
Literal minUInt(const Literal& other) const;
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index c3a2ddf7a..afaafe5e4 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -1070,6 +1070,14 @@ Literal Literal::subSatUI16(const Literal& other) const {
return Literal(sub_sat_u<uint16_t>(geti32(), other.geti32()));
}
+Literal Literal::q15MulrSatSI16(const Literal& other) const {
+ int64_t value =
+ (int64_t(geti32()) * int64_t(other.geti32()) + 0x4000LL) >> 15LL;
+ int64_t lower = std::numeric_limits<int16_t>::min();
+ int64_t upper = std::numeric_limits<int16_t>::max();
+ return Literal(int16_t(std::min(std::max(value, lower), upper)));
+}
+
Literal Literal::mul(const Literal& other) const {
switch (type.getBasic()) {
case Type::i32:
@@ -2201,7 +2209,8 @@ Literal Literal::avgrUI16x8(const Literal& other) const {
return binary<8, &Literal::getLanesUI16x8, &Literal::avgrUInt>(*this, other);
}
Literal Literal::q15MulrSatSI16x8(const Literal& other) const {
- WASM_UNREACHABLE("TODO: implement Q15 rounding, saturating multiplication");
+ return binary<8, &Literal::getLanesSI16x8, &Literal::q15MulrSatSI16>(*this,
+ other);
}
Literal Literal::addI32x4(const Literal& other) const {
return binary<4, &Literal::getLanesI32x4, &Literal::add>(*this, other);
diff --git a/test/spec/simd.wast b/test/spec/simd.wast
index 0eda03fc5..9a76fec3b 100644
--- a/test/spec/simd.wast
+++ b/test/spec/simd.wast
@@ -151,7 +151,7 @@
(func (export "i16x8.max_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.max_s (local.get $0) (local.get $1)))
(func (export "i16x8.max_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.max_u (local.get $0) (local.get $1)))
(func (export "i16x8.avgr_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.avgr_u (local.get $0) (local.get $1)))
- ;; TODO: Q15 rounding, saturating multiplication
+ (func (export "i16x8.q15mulr_sat_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.q15mulr_sat_s (local.get $0) (local.get $1)))
;; TODO: extending multiplications
(func (export "i32x4.abs") (param $0 v128) (result v128) (i32x4.abs (local.get $0)))
(func (export "i32x4.neg") (param $0 v128) (result v128) (i32x4.neg (local.get $0)))
@@ -783,6 +783,13 @@
)
(v128.const i16x8 384 32641 32768 32768 17280 38912 64640 16384)
)
+(assert_return
+ (invoke "i16x8.q15mulr_sat_s"
+ (v128.const i16x8 -1 -16383 32765 65535 -32768 65535 -16385 -32768)
+ (v128.const i16x8 -1 -16384 1 -32768 -32768 1 -16384 -1)
+ )
+ (v128.const i16x8 0 8192 1 1 32767 0 8193 1)
+)
;; i32x4 arithmetic
(assert_return (invoke "i32x4.abs" (v128.const i32x4 0 1 0x80000000 0x80000001)) (v128.const i32x4 0 1 0x80000000 0x7fffffff))