diff --git a/src/Language/Wasm/Interpreter.hs b/src/Language/Wasm/Interpreter.hs index 60585a4..af22ace 100644 --- a/src/Language/Wasm/Interpreter.hs +++ b/src/Language/Wasm/Interpreter.hs @@ -1709,13 +1709,19 @@ eval budget store inst FunctionInstance { funcType, moduleInstance, code = Funct step ctx@EvalCtx{ stack = (VV128 v:rest) } (V128AllTrue shape) = let r = case shape of I8x16 -> all (/= 0) $ ByteArray.indexByteArray @Word8 v <$> [0..15] - I16x8 -> all (/= 0) $ ByteArray.indexByteArray @Word16 v <$> [0..8] - I32x4 -> all (/= 0) $ ByteArray.indexByteArray @Word32 v <$> [0..4] - I64x2 -> all (/= 0) $ ByteArray.indexByteArray @Word64 v <$> [0..2] - F32x4 -> all (/= 0) $ wordToFloat . ByteArray.indexByteArray @Word32 v <$> [0..4] - F64x2 -> all (/= 0) $ wordToDouble . ByteArray.indexByteArray @Word64 v <$> [0..2] + I16x8 -> all (/= 0) $ ByteArray.indexByteArray @Word16 v <$> [0..7] + I32x4 -> all (/= 0) $ ByteArray.indexByteArray @Word32 v <$> [0..3] + I64x2 -> all (/= 0) $ ByteArray.indexByteArray @Word64 v <$> [0..1] in return $ Done ctx { stack = VI32 (if r then 1 else 0) : rest } + step ctx@EvalCtx{ stack = (VV128 v:rest) } (V128BitMask shape) = + let r = foldr (.|.) 0 $ case shape of + I8x16 -> (\i -> flip shiftL i . flip shiftR 7 . fromIntegral $ ByteArray.indexByteArray @Word8 v i) <$> [0..15] + I16x8 -> (\i -> flip shiftL i . flip shiftR 15 . fromIntegral $ ByteArray.indexByteArray @Word16 v i) <$> [0..7] + I32x4 -> (\i -> flip shiftL i . flip shiftR 31 . fromIntegral $ ByteArray.indexByteArray @Word32 v i) <$> [0..3] + I64x2 -> (\i -> flip shiftL i . fromIntegral $ flip shiftR 63 $ ByteArray.indexByteArray @Word64 v i) <$> [0..1] + in + return $ Done ctx { stack = VI32 r : rest } step ctx@EvalCtx{ stack = (VV128 c:VV128 v2:VV128 v1:rest) } V128BitSelect = let bitselect idx = let w1 = ByteArray.indexByteArray @Word64 v1 idx in diff --git a/src/Language/Wasm/Parser.y b/src/Language/Wasm/Parser.y index 6e63017..0a7721e 100644 --- a/src/Language/Wasm/Parser.y +++ b/src/Language/Wasm/Parser.y @@ -398,8 +398,6 @@ import Language.Wasm.Lexer ( 'i16x8.all_true' { Lexeme _ (TKeyword "i16x8.all_true") } 'i32x4.all_true' { Lexeme _ (TKeyword "i32x4.all_true") } 'i64x2.all_true' { Lexeme _ (TKeyword "i64x2.all_true") } -'f32x4.all_true' { Lexeme _ (TKeyword "f32x4.all_true") } -'f64x2.all_true' { Lexeme _ (TKeyword "f64x2.all_true") } 'v128.not' { Lexeme _ (TKeyword "v128.not") } 'v128.and' { Lexeme _ (TKeyword "v128.and") } 'v128.andnot' { Lexeme _ (TKeyword "v128.andnot") } @@ -415,6 +413,10 @@ import Language.Wasm.Lexer ( 'i16x8.sub' { Lexeme _ (TKeyword "i16x8.sub") } 'i32x4.sub' { Lexeme _ (TKeyword "i32x4.sub") } 'i64x2.sub' { Lexeme _ (TKeyword "i64x2.sub") } +'i8x16.bitmask' { Lexeme _ (TKeyword "i8x16.bitmask") } +'i16x8.bitmask' { Lexeme _ (TKeyword "i16x8.bitmask") } +'i32x4.bitmask' { Lexeme _ (TKeyword "i32x4.bitmask") } +'i64x2.bitmask' { Lexeme _ (TKeyword "i64x2.bitmask") } -- script extension 'binary' { Lexeme _ (TKeyword "binary") } 'quote' { Lexeme _ (TKeyword "quote") } @@ -839,8 +841,6 @@ plaininstr :: { PlainInstr } | 'i16x8.all_true' { V128AllTrue I16x8 } | 'i32x4.all_true' { V128AllTrue I32x4 } | 'i64x2.all_true' { V128AllTrue I64x2 } - | 'f32x4.all_true' { V128AllTrue F32x4 } - | 'f64x2.all_true' { V128AllTrue F64x2 } | 'i8x16.extract_lane_s' lane_index { V128ExtractLane I8x16 $2 True } | 'i16x8.extract_lane_s' lane_index { V128ExtractLane I16x8 $2 True } | 'i8x16.extract_lane_u' lane_index { V128ExtractLane I8x16 $2 False } @@ -863,6 +863,10 @@ plaininstr :: { PlainInstr } | 'i16x8.sub' { IBinOp (BS128 I16x8) ISub } | 'i32x4.sub' { IBinOp (BS128 I32x4) ISub } | 'i64x2.sub' { IBinOp (BS128 I64x2) ISub } + | 'i8x16.bitmask' { V128BitMask I8x16 } + | 'i16x8.bitmask' { V128BitMask I16x8 } + | 'i32x4.bitmask' { V128BitMask I32x4 } + | 'i64x2.bitmask' { V128BitMask I64x2 } typeuse(next) : '(' typeuse1(folded_instr_list(next), instruction_list(next)) { @@ -1588,6 +1592,7 @@ data PlainInstr = | V128ExtractLane SimdShape Natural Bool | V128ReplaceLane SimdShape Natural | V128AllTrue SimdShape + | V128BitMask SimdShape | V128AnyTrue | V128BitSelect | I8x16Shuffle [Int] @@ -2169,6 +2174,7 @@ desugarize fields = do synInstrToStruct _ (PlainInstr (V128ExtractLane shape idx sign)) = return $ S.V128ExtractLane shape idx sign synInstrToStruct _ (PlainInstr (V128ReplaceLane shape idx)) = return $ S.V128ReplaceLane shape idx synInstrToStruct _ (PlainInstr (V128AllTrue shape)) = return $ S.V128AllTrue shape + synInstrToStruct _ (PlainInstr (V128BitMask shape)) = return $ S.V128BitMask shape synInstrToStruct _ (PlainInstr V128AnyTrue) = return $ S.V128AnyTrue synInstrToStruct _ (PlainInstr V128BitSelect) = return $ S.V128BitSelect synInstrToStruct _ (PlainInstr (I8x16Shuffle idxs)) = return $ S.I8x16Shuffle idxs diff --git a/src/Language/Wasm/Structure.hs b/src/Language/Wasm/Structure.hs index 47a4ed8..5954edc 100644 --- a/src/Language/Wasm/Structure.hs +++ b/src/Language/Wasm/Structure.hs @@ -254,6 +254,7 @@ data Instruction index = | V128ExtractLane SimdShape index {- signed -} Bool | V128ReplaceLane SimdShape index | V128AllTrue SimdShape + | V128BitMask SimdShape | V128AnyTrue | V128BitSelect | I8x16Swizzle diff --git a/src/Language/Wasm/Validate.hs b/src/Language/Wasm/Validate.hs index 2a301f5..7e561ed 100644 --- a/src/Language/Wasm/Validate.hs +++ b/src/Language/Wasm/Validate.hs @@ -611,6 +611,8 @@ getInstrType _ V128AnyTrue = return $ V128 ==> I32 getInstrType _ V128BitSelect = return $ [V128, V128, V128] ==> V128 +getInstrType _ (V128BitMask _) = + return $ V128 ==> I32 getShapeElemType :: SimdShape -> ValueType getShapeElemType I8x16 = I32 diff --git a/tests/Test.hs b/tests/Test.hs index e64cf15..8ca11db 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_load8_lane.wast"] + -- let files = ["simd_boolean.wast"] scriptTestCases <- (`mapM` files) $ \file -> do test <- LBS.readFile ("tests/spec/" ++ file) return $ testCase file $ do