module LLVM.Extra.ExtensionCheck.X86 ( sse1, sse2, sse3, ssse3, sse41, sse42, ) where import qualified LLVM.Extra.Extension as Ext import Data.Word (Word32, ) import Data.Bits (testBit, ) import System.Cpuid (cpuid, ) import System.IO.Unsafe (unsafePerformIO, ) {- I expect that the cpuid does not suddenly change and thus calling unsafePerformIO is safe. -} subtarget :: String -> (Word32 -> Word32 -> Bool) -> Ext.Subtarget subtarget name q = Ext.Subtarget "x86" name (return $ unsafePerformIO $ check q) check :: (Word32 -> Word32 -> Bool) -> IO Bool check q = do (high, _, _, _) <- cpuid 0 let featureId = 1 if featureId>high then return False else do (_,_,ecx,edx) <- cpuid featureId return (q ecx edx) -- * target specific extensions sse1 :: Ext.Subtarget sse1 = subtarget "sse" (\_ecx edx -> testBit edx 25) sse2 :: Ext.Subtarget sse2 = subtarget "sse2" (\_ecx edx -> testBit edx 26) sse3 :: Ext.Subtarget sse3 = subtarget "sse3" (\ecx _edx -> testBit ecx 0) ssse3 :: Ext.Subtarget ssse3 = subtarget "ssse3" (\ecx _edx -> testBit ecx 9) sse41 :: Ext.Subtarget sse41 = subtarget "sse41" (\ecx _edx -> testBit ecx 19) sse42 :: Ext.Subtarget sse42 = subtarget "sse42" (\ecx _edx -> testBit ecx 20)