module LLVM.Extra.ExtensionCheck.X86 (
   sse1, sse2, sse3, ssse3, sse41, sse42,
   ) where

import qualified LLVM.Extra.Extension as Ext
import qualified System.Cpuid as CPUID
import System.IO.Unsafe (unsafePerformIO, )

{-
I expect that the cpuid does not suddenly change
and thus calling unsafePerformIO is safe.
-}
subtarget ::
   String ->
   (CPUID.FlagSet CPUID.Feature1C -> CPUID.FlagSet CPUID.Feature1D -> Bool) ->
   Ext.Subtarget
subtarget name q =
   Ext.Subtarget "x86" name
      (return $ unsafePerformIO $ check q)

check ::
   (CPUID.FlagSet CPUID.Feature1C -> CPUID.FlagSet CPUID.Feature1D -> Bool) ->
   IO Bool
check q =
   fmap (uncurry q) $ CPUID.features


-- * target specific extensions

sse1 :: Ext.Subtarget
sse1 = subtarget "sse" (\_ecx edx -> CPUID.testFlag CPUID.sse edx)

sse2 :: Ext.Subtarget
sse2 = subtarget "sse2" (\_ecx edx -> CPUID.testFlag CPUID.sse2 edx)

sse3 :: Ext.Subtarget
sse3 = subtarget "sse3" (\ecx _edx -> CPUID.testFlag CPUID.sse3 ecx)

ssse3 :: Ext.Subtarget
ssse3 = subtarget "ssse3" (\ecx _edx -> CPUID.testFlag CPUID.ssse3 ecx)

sse41 :: Ext.Subtarget
sse41 = subtarget "sse41" (\ecx _edx -> CPUID.testFlag CPUID.sse4_1 ecx)

sse42 :: Ext.Subtarget
sse42 = subtarget "sse42" (\ecx _edx -> CPUID.testFlag CPUID.sse4_2 ecx)