Skip to content

Commit

Permalink
Implement f{32,64}.sub instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Aug 14, 2020
1 parent 7106040 commit 7edb382
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 2 deletions.
12 changes: 10 additions & 2 deletions lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
binary_op(stack, std::plus<float>{});
break;
}
case Instr::f32_sub:
{
binary_op(stack, std::minus<float>{});
break;
}
case Instr::f32_mul:
{
binary_op(stack, std::multiplies<float>{});
Expand Down Expand Up @@ -1625,6 +1630,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
binary_op(stack, std::plus<double>{});
break;
}
case Instr::f64_sub:
{
binary_op(stack, std::minus<double>{});
break;
}
case Instr::f64_mul:
{
binary_op(stack, std::multiplies<double>{});
Expand Down Expand Up @@ -1789,12 +1799,10 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
case Instr::f32_floor:
case Instr::f32_trunc:
case Instr::f32_nearest:
case Instr::f32_sub:
case Instr::f64_ceil:
case Instr::f64_floor:
case Instr::f64_trunc:
case Instr::f64_nearest:
case Instr::f64_sub:
case Instr::f32_demote_f64:
case Instr::i32_reinterpret_f32:
case Instr::i64_reinterpret_f64:
Expand Down
67 changes: 67 additions & 0 deletions test/unittests/execute_floating_point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ TYPED_TEST(execute_floating_point_types, binop_nan_propagation)
// Only f32 variants, but f64 variants are going to be covered as well.
constexpr Instr opcodes[] = {
Instr::f32_add,
Instr::f32_sub,
Instr::f32_mul,
Instr::f32_div,
Instr::f32_min,
Expand Down Expand Up @@ -538,6 +539,72 @@ TYPED_TEST(execute_floating_point_types, add)
EXPECT_THAT(exec(TypeParam{0x0.287p2}, TypeParam{0x1.FFp4}), Result(TypeParam{0x1.048Ep5}));
}

TYPED_TEST(execute_floating_point_types, sub)
{
using FP = FP<TypeParam>;
using Limits = typename FP::Limits;

auto instance = instantiate(parse(this->get_binop_code(Instr::f32_sub)));
const auto exec = [&](auto arg1, auto arg2) { return execute(*instance, 0, {arg1, arg2}); };

// fsub(+-inf, +-inf) = nan:canonical
EXPECT_THAT(exec(Limits::infinity(), Limits::infinity()), CanonicalNaN(TypeParam{}));
EXPECT_THAT(exec(-Limits::infinity(), -Limits::infinity()), CanonicalNaN(TypeParam{}));

// fsub(+-inf, -+inf) = +-inf
EXPECT_THAT(exec(Limits::infinity(), -Limits::infinity()), Result(Limits::infinity()));
EXPECT_THAT(exec(-Limits::infinity(), Limits::infinity()), Result(-Limits::infinity()));

// fsub(+-O, +-0) = +0
EXPECT_THAT(exec(TypeParam{0.0}, TypeParam{0.0}), Result(TypeParam{0.0}));
EXPECT_THAT(exec(-TypeParam{0.0}, -TypeParam{0.0}), Result(TypeParam{0.0}));

// fsub(+-0, -+0) = +-0
EXPECT_THAT(exec(TypeParam{0.0}, -TypeParam{0.0}), Result(TypeParam{0.0}));
EXPECT_THAT(exec(-TypeParam{0.0}, TypeParam{0.0}), Result(-TypeParam{0.0}));

// fsub(z1, +-0) = z1 (for z1 = +-inf)
EXPECT_THAT(exec(Limits::infinity(), TypeParam{0.0}), Result(Limits::infinity()));
EXPECT_THAT(exec(Limits::infinity(), -TypeParam{0.0}), Result(Limits::infinity()));
EXPECT_THAT(exec(-Limits::infinity(), TypeParam{0.0}), Result(-Limits::infinity()));
EXPECT_THAT(exec(-Limits::infinity(), -TypeParam{0.0}), Result(-Limits::infinity()));

for (const auto q : this->positive_special_values)
{
// fsub(z1, +-inf) = -+inf (for z1 = +-q)
EXPECT_THAT(exec(q, Limits::infinity()), Result(-Limits::infinity()));
EXPECT_THAT(exec(q, -Limits::infinity()), Result(Limits::infinity()));
EXPECT_THAT(exec(-q, Limits::infinity()), Result(-Limits::infinity()));
EXPECT_THAT(exec(-q, -Limits::infinity()), Result(Limits::infinity()));

// fsub(+-inf, z2) = +-inf (for z2 = +-q)
EXPECT_THAT(exec(Limits::infinity(), q), Result(Limits::infinity()));
EXPECT_THAT(exec(-Limits::infinity(), q), Result(-Limits::infinity()));
EXPECT_THAT(exec(Limits::infinity(), -q), Result(Limits::infinity()));
EXPECT_THAT(exec(-Limits::infinity(), -q), Result(-Limits::infinity()));

// fsub(z1, +-0) = z1 (for z1 = +-q)
EXPECT_THAT(exec(q, TypeParam{0.0}), Result(q));
EXPECT_THAT(exec(q, -TypeParam{0.0}), Result(q));
EXPECT_THAT(exec(-q, TypeParam{0.0}), Result(-q));
EXPECT_THAT(exec(-q, -TypeParam{0.0}), Result(-q));

// fsub(+-0, +-q2) = -+q2
EXPECT_THAT(exec(TypeParam{0.0}, q), Result(-q));
EXPECT_THAT(exec(-TypeParam{0.0}, -q), Result(q));

// Not part of the spec.
EXPECT_THAT(exec(TypeParam{0.0}, -q), Result(q));
EXPECT_THAT(exec(-TypeParam{0.0}, q), Result(-q));

// fsub(+-q, +-q) = +0
EXPECT_THAT(exec(q, q), Result(TypeParam{0.0}));
EXPECT_THAT(exec(-q, -q), Result(TypeParam{0.0}));
}

EXPECT_THAT(exec(TypeParam{0x1.048Ep5}, TypeParam{0x1.FFp4}), Result(TypeParam{0x0.287p2}));
}

TYPED_TEST(execute_floating_point_types, mul)
{
using FP = FP<TypeParam>;
Expand Down

0 comments on commit 7edb382

Please sign in to comment.