diff options
Diffstat (limited to 'src/wasm/literal.cpp')
-rw-r--r-- | src/wasm/literal.cpp | 62 |
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 |