summaryrefslogtreecommitdiff
path: root/src/wasm/literal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/literal.cpp')
-rw-r--r--src/wasm/literal.cpp62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 4753e5ca1..e761206bc 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -1610,6 +1610,32 @@ Literal Literal::copysign(const Literal& other) const {
}
}
+Literal Literal::fma(const Literal& left, const Literal& right) const {
+ switch (type.getBasic()) {
+ case Type::f32:
+ return Literal(::fmaf(left.getf32(), right.getf32(), getf32()));
+ break;
+ case Type::f64:
+ return Literal(::fma(left.getf64(), right.getf64(), getf64()));
+ break;
+ default:
+ WASM_UNREACHABLE("unexpected type");
+ }
+}
+
+Literal Literal::fms(const Literal& left, const Literal& right) const {
+ switch (type.getBasic()) {
+ case Type::f32:
+ return Literal(::fmaf(-left.getf32(), right.getf32(), getf32()));
+ break;
+ case Type::f64:
+ return Literal(::fma(-left.getf64(), right.getf64(), getf64()));
+ break;
+ default:
+ WASM_UNREACHABLE("unexpected type");
+ }
+}
+
template<typename LaneT, int Lanes>
static LaneArray<Lanes> getLanes(const Literal& val) {
assert(val.type == Type::v128);
@@ -2548,6 +2574,42 @@ Literal Literal::swizzleI8x16(const Literal& other) const {
return Literal(result);
}
+namespace {
+template<int Lanes,
+ LaneArray<Lanes> (Literal::*IntoLanes)() const,
+ Literal (Literal::*TernaryOp)(const Literal&, const Literal&) const>
+static Literal ternary(const Literal& a, const Literal& b, const Literal& c) {
+ LaneArray<Lanes> x = (a.*IntoLanes)();
+ LaneArray<Lanes> y = (b.*IntoLanes)();
+ LaneArray<Lanes> z = (c.*IntoLanes)();
+ LaneArray<Lanes> r;
+ for (size_t i = 0; i < Lanes; ++i) {
+ r[i] = (x[i].*TernaryOp)(y[i], z[i]);
+ }
+ return Literal(r);
+}
+} // namespace
+
+Literal Literal::relaxedFmaF32x4(const Literal& left,
+ const Literal& right) const {
+ return ternary<4, &Literal::getLanesF32x4, &Literal::fma>(*this, left, right);
+}
+
+Literal Literal::relaxedFmsF32x4(const Literal& left,
+ const Literal& right) const {
+ return ternary<4, &Literal::getLanesF32x4, &Literal::fms>(*this, left, right);
+}
+
+Literal Literal::relaxedFmaF64x2(const Literal& left,
+ const Literal& right) const {
+ return ternary<2, &Literal::getLanesF64x2, &Literal::fma>(*this, left, right);
+}
+
+Literal Literal::relaxedFmsF64x2(const Literal& left,
+ const Literal& right) const {
+ return ternary<2, &Literal::getLanesF64x2, &Literal::fms>(*this, left, right);
+}
+
bool Literal::isSubRtt(const Literal& other) const {
assert(type.isRtt() && other.type.isRtt());
// For this literal to be a sub-rtt of the other rtt, the supers must be a