message: Implement f{32,64}.max instructions
diff: @@ -529,6 +529,18 @@ inline constexpr T fmin(T a, T b) noexcept
  return b < a ? b : a;
  }
  +template <typename T>
  +inline constexpr T fmax(T a, T b) noexcept
  +{
  + if (std::isnan(a) || std::isnan(b))
  + return std::numeric_limits<T>::quiet_NaN();
  +
  + if (a == 0 && b == 0 && (std::signbit(a) == 0 || std::signbit(b) == 0))
  + return T{0};
  +
  + return a < b ? b : a;
  +}
  +
  std::optional<uint32_t> find_export(const Module& module, ExternalKind kind, std::string_view name)
  {
  const auto it = std::find_if(module.exportsec.begin(), module.exportsec.end(),
  @@ -1571,6 +1583,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
  binary_op(stack, fmin<float>);
  break;
  }
  + case Instr::f32_max:
  + {
  + binary_op(stack, fmax<float>);
  + break;
  + }
  case Instr::f32_copysign:
  {
  // TODO: This is not optimal implementation. The std::copysign() is inlined, but
  @@ -1613,6 +1630,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
  binary_op(stack, fmin<double>);
  break;
  }
  + case Instr::f64_max:
  + {
  + binary_op(stack, fmax<double>);
  + break;
  + }
  case Instr::f64_copysign:
  {
  binary_op(stack, static_cast<double (*)(double, double)>(std::copysign));
  @@ -1759,14 +1781,12 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
  case Instr::f32_nearest:
  case Instr::f32_sub:
  case Instr::f32_mul:
  - case Instr::f32_max:
  case Instr::f64_ceil:
  case Instr::f64_floor:
  case Instr::f64_trunc:
  case Instr::f64_nearest:
  case Instr::f64_sub:
  case Instr::f64_mul:
  - case Instr::f64_max:
  case Instr::f32_demote_f64:
  case Instr::i32_reinterpret_f32:
  case Instr::i64_reinterpret_f64:
  