diff --git a/src/Language/Wasm/Interpreter.hs b/src/Language/Wasm/Interpreter.hs index e64a13e..00aecfd 100644 --- a/src/Language/Wasm/Interpreter.hs +++ b/src/Language/Wasm/Interpreter.hs @@ -162,6 +162,16 @@ zeroAwareMax a b | isNaN b = b | otherwise = maxNum a b +nanAwareMin :: IEEE a => a -> a -> a +nanAwareMin a b + | isNaN a = a + | otherwise = minNum a b + +nanAwareMax :: IEEE a => a -> a -> a +nanAwareMax a b + | isNaN a = a + | otherwise = maxNum a b + floatFloor :: Float -> Float floatFloor a | isNaN a = a @@ -1932,6 +1942,20 @@ eval budget store inst FunctionInstance { funcType, moduleInstance, code = Funct _ -> error "impossible due to validation" in return $ Done ctx { stack = VV128 r : rest } + step ctx@EvalCtx{ stack = (VV128 v2:VV128 v1:rest) } (FBinOp (BS128 shape) FPMin) = + let r = case shape of + F32x4 -> lanewise @Word32 shape v1 v2 $ \a b -> floatToWord $ nanAwareMin (wordToFloat a) (wordToFloat b) + F64x2 -> lanewise @Word64 shape v1 v2 $ \a b -> doubleToWord $ nanAwareMin (wordToDouble a) (wordToDouble b) + _ -> error "impossible due to validation" + in + return $ Done ctx { stack = VV128 r : rest } + step ctx@EvalCtx{ stack = (VV128 v2:VV128 v1:rest) } (FBinOp (BS128 shape) FPMax) = + let r = case shape of + F32x4 -> lanewise @Word32 shape v1 v2 $ \a b -> floatToWord $ nanAwareMax (wordToFloat a) (wordToFloat b) + F64x2 -> lanewise @Word64 shape v1 v2 $ \a b -> doubleToWord $ nanAwareMax (wordToDouble a) (wordToDouble b) + _ -> error "impossible due to validation" + in + return $ Done ctx { stack = VV128 r : rest } step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FEq) = return $ Done ctx { stack = VI32 (if v1 == v2 then 1 else 0) : rest } step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FNe) = diff --git a/src/Language/Wasm/Parser.y b/src/Language/Wasm/Parser.y index a733446..6335974 100644 --- a/src/Language/Wasm/Parser.y +++ b/src/Language/Wasm/Parser.y @@ -532,6 +532,10 @@ import Language.Wasm.Lexer ( 'f64x2.min' { Lexeme _ (TKeyword "f64x2.min") } 'f32x4.max' { Lexeme _ (TKeyword "f32x4.max") } 'f64x2.max' { Lexeme _ (TKeyword "f64x2.max") } +'f32x4.pmin' { Lexeme _ (TKeyword "f32x4.pmin") } +'f64x2.pmin' { Lexeme _ (TKeyword "f64x2.pmin") } +'f32x4.pmax' { Lexeme _ (TKeyword "f32x4.pmax") } +'f64x2.pmax' { Lexeme _ (TKeyword "f64x2.pmax") } 'f32x4.abs' { Lexeme _ (TKeyword "f32x4.abs") } 'f64x2.abs' { Lexeme _ (TKeyword "f64x2.abs") } 'f32x4.neg' { Lexeme _ (TKeyword "f32x4.neg") } @@ -1122,6 +1126,10 @@ plaininstr :: { PlainInstr } | 'f64x2.min' { FBinOp (BS128 F64x2) FMin } | 'f32x4.max' { FBinOp (BS128 F32x4) FMax } | 'f64x2.max' { FBinOp (BS128 F64x2) FMax } + | 'f32x4.pmin' { FBinOp (BS128 F32x4) FPMin } + | 'f64x2.pmin' { FBinOp (BS128 F64x2) FPMin } + | 'f32x4.pmax' { FBinOp (BS128 F32x4) FPMax } + | 'f64x2.pmax' { FBinOp (BS128 F64x2) FPMax } | 'f32x4.abs' { FUnOp (BS128 F32x4) FAbs } | 'f64x2.abs' { FUnOp (BS128 F64x2) FAbs } | 'f32x4.neg' { FUnOp (BS128 F32x4) FNeg } diff --git a/src/Language/Wasm/Structure.hs b/src/Language/Wasm/Structure.hs index 8fde116..86627dc 100644 --- a/src/Language/Wasm/Structure.hs +++ b/src/Language/Wasm/Structure.hs @@ -110,7 +110,7 @@ data IRelOp = IEq | INe | ILtU | ILtS | IGtU | IGtS | ILeU | ILeS | IGeU | IGeS data FUnOp = FAbs | FNeg | FCeil | FFloor | FTrunc | FNearest | FSqrt deriving (Show, Eq, Generic, NFData) -data FBinOp = FAdd | FSub | FMul | FDiv | FMin | FMax | FCopySign deriving (Show, Eq, Generic, NFData) +data FBinOp = FAdd | FSub | FMul | FDiv | FMin | FMax | FCopySign | FPMin | FPMax deriving (Show, Eq, Generic, NFData) data FRelOp = FEq | FNe | FLt | FGt | FLe | FGe deriving (Show, Eq, Generic, NFData) diff --git a/tests/Test.hs b/tests/Test.hs index e774362..b8200da 100644 --- a/tests/Test.hs +++ b/tests/Test.hs @@ -20,7 +20,7 @@ main = do filter (List.isPrefixOf "simd") . filter (List.isSuffixOf ".wast") <$> Directory.listDirectory "tests/spec" - -- let files = ["simd_i32x4_extadd_pairwise_i16x8.wast"] + -- let files = ["simd_f32x4_pmin_pmax.wast"] scriptTestCases <- (`mapM` files) $ \file -> do test <- LBS.readFile ("tests/spec/" ++ file) return $ testCase file $ do