{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}
{- |
Description: Detect Arm features at runtime

This module provides the basic interface to detect CPU features.
The availability is indicated by a boolean variable (@b\<FEATRUE NAME\>@).
-}
module System.CPUFeatures.Arm.Bool
  (bFEAT_AES
  ,bFEAT_AFP
  ,bFEAT_BF16
  ,bFEAT_BTI
  ,bFEAT_CSV2
  ,bFEAT_CSV3
  ,bFEAT_DIT
  ,bFEAT_DotProd
  ,bFEAT_DPB
  ,bFEAT_DPB2
  ,bFEAT_ECV
  ,bFEAT_FCMA
  ,bFEAT_FHM
  ,bFEAT_FlagM
  ,bFEAT_FlagM2
  ,bFEAT_FP16
  ,bFEAT_FPAC
  ,bFEAT_FRINTTS
  ,bFEAT_I8MM
  ,bFEAT_JSCVT
  ,bFEAT_LRCPC
  ,bFEAT_LRCPC2
  ,bFEAT_LSE
  ,bFEAT_LSE2
  ,bFEAT_PAuth
  ,bFEAT_PAuth2
  ,bFEAT_PMULL
  ,bFEAT_RDM
  ,bFEAT_RPRES
  ,bFEAT_SB
  ,bFEAT_SHA1
  ,bFEAT_SHA256
  ,bFEAT_SHA3
  ,bFEAT_SHA512
  ,bFEAT_SME
  ,bFEAT_SME_F64F64
  ,bFEAT_SME_I16I64
  ,bFEAT_SME2
  ,bFEAT_SPECRES
  ,bFEAT_SSBS
  ,bFEAT_SVE
  ,bFEAT_SVE2
  ,bFEAT_WFxT
  ) where
#if defined(aarch64_HOST_ARCH) && defined(darwin_HOST_OS)
import GHC.Exts (Addr#)
#endif
#if defined(aarch64_HOST_ARCH) && defined(linux_HOST_OS)
import Hwcap
import Data.Bits
#endif

bFEAT_AES :: Bool
bFEAT_AFP :: Bool
bFEAT_BF16 :: Bool
bFEAT_BTI :: Bool
bFEAT_CSV2 :: Bool
bFEAT_CSV3 :: Bool
bFEAT_DIT :: Bool
bFEAT_DotProd :: Bool
bFEAT_DPB :: Bool
bFEAT_DPB2 :: Bool
bFEAT_ECV :: Bool
bFEAT_FCMA :: Bool
bFEAT_FHM :: Bool
bFEAT_FlagM :: Bool
bFEAT_FlagM2 :: Bool
bFEAT_FP16 :: Bool
bFEAT_FPAC :: Bool
bFEAT_FRINTTS :: Bool
bFEAT_I8MM :: Bool
bFEAT_JSCVT :: Bool
bFEAT_LRCPC :: Bool
bFEAT_LRCPC2 :: Bool
bFEAT_LSE :: Bool
bFEAT_LSE2 :: Bool
bFEAT_PAuth :: Bool
bFEAT_PAuth2 :: Bool
bFEAT_PMULL :: Bool
bFEAT_RDM :: Bool
bFEAT_RPRES :: Bool
bFEAT_SB :: Bool
bFEAT_SHA1 :: Bool
bFEAT_SHA256 :: Bool
bFEAT_SHA3 :: Bool
bFEAT_SHA512 :: Bool
bFEAT_SME :: Bool
bFEAT_SME_F64F64 :: Bool
bFEAT_SME_I16I64 :: Bool
bFEAT_SME2 :: Bool
bFEAT_SPECRES :: Bool
bFEAT_SSBS :: Bool
bFEAT_SVE :: Bool
bFEAT_SVE2 :: Bool
bFEAT_WFxT :: Bool

#if defined(aarch64_HOST_ARCH) && (defined(darwin_HOST_OS) || defined(linux_HOST_OS))

#if defined(darwin_HOST_OS)

foreign import ccall unsafe hs_cpu_features_sysctl :: Addr# -> Bool

{-# NOINLINE bFEAT_AES #-}
bFEAT_AES = hs_cpu_features_sysctl "hw.optional.arm.FEAT_AES"#

{-# NOINLINE bFEAT_AFP #-}
bFEAT_AFP = hs_cpu_features_sysctl "hw.optional.arm.FEAT_AFP"#

{-# NOINLINE bFEAT_BF16 #-}
bFEAT_BF16 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_BF16"#

{-# NOINLINE bFEAT_BTI #-}
bFEAT_BTI = hs_cpu_features_sysctl "hw.optional.arm.FEAT_BTI"#

{-# NOINLINE bFEAT_CSV2 #-}
bFEAT_CSV2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_CSV2"#

{-# NOINLINE bFEAT_CSV3 #-}
bFEAT_CSV3 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_CSV3"#

{-# NOINLINE bFEAT_DIT #-}
bFEAT_DIT = hs_cpu_features_sysctl "hw.optional.arm.FEAT_DIT"#

{-# NOINLINE bFEAT_DotProd #-}
bFEAT_DotProd = hs_cpu_features_sysctl "hw.optional.arm.FEAT_DotProd"#

{-# NOINLINE bFEAT_DPB #-}
bFEAT_DPB = hs_cpu_features_sysctl "hw.optional.arm.FEAT_DPB"#

{-# NOINLINE bFEAT_DPB2 #-}
bFEAT_DPB2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_DPB2"#

{-# NOINLINE bFEAT_ECV #-}
bFEAT_ECV = hs_cpu_features_sysctl "hw.optional.arm.FEAT_ECV"#

{-# NOINLINE bFEAT_FCMA #-}
bFEAT_FCMA = hs_cpu_features_sysctl "hw.optional.arm.FEAT_FCMA"#

{-# NOINLINE bFEAT_FHM #-}
bFEAT_FHM = hs_cpu_features_sysctl "hw.optional.arm.FEAT_FHM"#

{-# NOINLINE bFEAT_FlagM #-}
bFEAT_FlagM = hs_cpu_features_sysctl "hw.optional.arm.FEAT_FlagM"#

{-# NOINLINE bFEAT_FlagM2 #-}
bFEAT_FlagM2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_FlagM2"#

{-# NOINLINE bFEAT_FP16 #-}
bFEAT_FP16 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_FP16"#

{-# NOINLINE bFEAT_FPAC #-}
bFEAT_FPAC = hs_cpu_features_sysctl "hw.optional.arm.FEAT_FPAC"#

{-# NOINLINE bFEAT_FRINTTS #-}
bFEAT_FRINTTS = hs_cpu_features_sysctl "hw.optional.arm.FEAT_FRINTTS"#

{-# NOINLINE bFEAT_I8MM #-}
bFEAT_I8MM = hs_cpu_features_sysctl "hw.optional.arm.FEAT_I8MM"#

{-# NOINLINE bFEAT_JSCVT #-}
bFEAT_JSCVT = hs_cpu_features_sysctl "hw.optional.arm.FEAT_JSCVT"#

{-# NOINLINE bFEAT_LRCPC #-}
bFEAT_LRCPC = hs_cpu_features_sysctl "hw.optional.arm.FEAT_LRCPC"#

{-# NOINLINE bFEAT_LRCPC2 #-}
bFEAT_LRCPC2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_LRCPC2"#

{-# NOINLINE bFEAT_LSE #-}
bFEAT_LSE = hs_cpu_features_sysctl "hw.optional.arm.FEAT_LSE"#

{-# NOINLINE bFEAT_LSE2 #-}
bFEAT_LSE2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_LSE2"#

{-# NOINLINE bFEAT_PAuth #-}
bFEAT_PAuth = hs_cpu_features_sysctl "hw.optional.arm.FEAT_PAuth"#

{-# NOINLINE bFEAT_PAuth2 #-}
bFEAT_PAuth2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_PAuth2"#

{-# NOINLINE bFEAT_PMULL #-}
bFEAT_PMULL = hs_cpu_features_sysctl "hw.optional.arm.FEAT_PMULL"#

{-# NOINLINE bFEAT_RDM #-}
bFEAT_RDM = hs_cpu_features_sysctl "hw.optional.arm.FEAT_RDM"#

{-# NOINLINE bFEAT_RPRES #-}
bFEAT_RPRES = hs_cpu_features_sysctl "hw.optional.arm.FEAT_RPRES"#

{-# NOINLINE bFEAT_SB #-}
bFEAT_SB = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SB"#

{-# NOINLINE bFEAT_SHA1 #-}
bFEAT_SHA1 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SHA1"#

{-# NOINLINE bFEAT_SHA256 #-}
bFEAT_SHA256 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SHA256"#

{-# NOINLINE bFEAT_SHA3 #-}
bFEAT_SHA3 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SHA3"#

{-# NOINLINE bFEAT_SHA512 #-}
bFEAT_SHA512 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SHA512"#

{-# NOINLINE bFEAT_SME #-}
bFEAT_SME = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SME"#

{-# NOINLINE bFEAT_SME_F64F64 #-}
bFEAT_SME_F64F64 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SME_F64F64"#

{-# NOINLINE bFEAT_SME_I16I64 #-}
bFEAT_SME_I16I64 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SME_I16I64"#

{-# NOINLINE bFEAT_SME2 #-}
bFEAT_SME2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SME2"#

{-# NOINLINE bFEAT_SPECRES #-}
bFEAT_SPECRES = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SPECRES"#

{-# NOINLINE bFEAT_SSBS #-}
bFEAT_SSBS = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SSBS"#

{-# NOINLINE bFEAT_SVE #-}
bFEAT_SVE = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SVE"#

{-# NOINLINE bFEAT_SVE2 #-}
bFEAT_SVE2 = hs_cpu_features_sysctl "hw.optional.arm.FEAT_SVE2"#

{-# NOINLINE bFEAT_WFxT #-}
bFEAT_WFxT = hs_cpu_features_sysctl "hw.optional.arm.FEAT_WFxT"#

#elif defined(linux_HOST_OS)

bFEAT_AES = hwcap .&. hwcap_AES /= 0
bFEAT_AFP = hwcap2 .&. hwcap2_AFP /= 0
bFEAT_BF16 = hwcap2 .&. hwcap2_BF16 /= 0
bFEAT_BTI = hwcap2 .&. hwcap2_BTI /= 0
bFEAT_CSV2 = False
bFEAT_CSV3 = False
bFEAT_DIT = hwcap .&. hwcap_DIT /= 0
bFEAT_DotProd = hwcap .&. hwcap_ASIMDDP /= 0
bFEAT_DPB = hwcap .&. hwcap_DCPOP /= 0
bFEAT_DPB2 = hwcap2 .&. hwcap2_DCPODP /= 0
bFEAT_ECV = False
bFEAT_FCMA = hwcap .&. hwcap_FCMA /= 0
bFEAT_FHM = hwcap .&. hwcap_ASIMDFHM /= 0
bFEAT_FlagM = hwcap .&. hwcap_FLAGM /= 0
bFEAT_FlagM2 = hwcap2 .&. hwcap2_FLAGM2 /= 0
bFEAT_FP16 = hwcap .&. hwcap_FPHP /= 0 -- hwcap_ASIMDHP?
bFEAT_FPAC = False
bFEAT_FRINTTS = hwcap2 .&. hwcap2_FRINT /= 0
bFEAT_I8MM = hwcap2 .&. hwcap2_I8MM /= 0
bFEAT_JSCVT = hwcap .&. hwcap_JSCVT /= 0
bFEAT_LRCPC = hwcap .&. hwcap_LRCPC /= 0
bFEAT_LRCPC2 = hwcap .&. hwcap_ILRCPC /= 0
bFEAT_LSE = hwcap .&. hwcap_ATOMICS /= 0
bFEAT_LSE2 = hwcap .&. hwcap_USCAT /= 0
bFEAT_PAuth = hwcap .&. hwcap_PACA /= 0
bFEAT_PAuth2 = False
bFEAT_PMULL = hwcap .&. hwcap_PMULL /= 0
bFEAT_RDM = hwcap .&. hwcap_ASIMDRDM /= 0
bFEAT_RPRES = hwcap2 .&. hwcap2_RPRES /= 0
bFEAT_SB = hwcap .&. hwcap_SB /= 0
bFEAT_SHA1 = hwcap .&. hwcap_SHA1 /= 0
bFEAT_SHA256 = hwcap .&. hwcap_SHA2 /= 0
bFEAT_SHA3 = hwcap .&. hwcap_SHA3 /= 0
bFEAT_SHA512 = hwcap .&. hwcap_SHA512 /= 0
bFEAT_SME = hwcap2 .&. hwcap2_SME /= 0
bFEAT_SME_F64F64 = hwcap2 .&. hwcap2_SME_F64F64 /= 0
bFEAT_SME_I16I64 = hwcap2 .&. hwcap2_SME_I16I64 /= 0
bFEAT_SME2 = hwcap2 .&. hwcap2_SME2 /= 0
bFEAT_SPECRES = False
bFEAT_SSBS = hwcap .&. hwcap_SSBS /= 0 -- FEAT_SSB2?
bFEAT_SVE = hwcap .&. hwcap_SVE /= 0
bFEAT_SVE2 = hwcap2 .&. hwcap2_SVE2 /= 0
bFEAT_WFxT = hwcap2 .&. hwcap2_WFXT /= 0

#else
#error bug
#endif

#else

{-# INLINE bFEAT_AES #-}
bFEAT_AES :: Bool
bFEAT_AES = Bool
False

{-# INLINE bFEAT_AFP #-}
bFEAT_AFP :: Bool
bFEAT_AFP = Bool
False

{-# INLINE bFEAT_BF16 #-}
bFEAT_BF16 :: Bool
bFEAT_BF16 = Bool
False

{-# INLINE bFEAT_BTI #-}
bFEAT_BTI :: Bool
bFEAT_BTI = Bool
False

{-# INLINE bFEAT_CSV2 #-}
bFEAT_CSV2 :: Bool
bFEAT_CSV2 = Bool
False

{-# INLINE bFEAT_CSV3 #-}
bFEAT_CSV3 :: Bool
bFEAT_CSV3 = Bool
False

{-# INLINE bFEAT_DIT #-}
bFEAT_DIT :: Bool
bFEAT_DIT = Bool
False

{-# INLINE bFEAT_DotProd #-}
bFEAT_DotProd :: Bool
bFEAT_DotProd = Bool
False

{-# INLINE bFEAT_DPB #-}
bFEAT_DPB :: Bool
bFEAT_DPB = Bool
False

{-# INLINE bFEAT_DPB2 #-}
bFEAT_DPB2 :: Bool
bFEAT_DPB2 = Bool
False

{-# INLINE bFEAT_ECV #-}
bFEAT_ECV :: Bool
bFEAT_ECV = Bool
False

{-# INLINE bFEAT_FCMA #-}
bFEAT_FCMA :: Bool
bFEAT_FCMA = Bool
False

{-# INLINE bFEAT_FHM #-}
bFEAT_FHM :: Bool
bFEAT_FHM = Bool
False

{-# INLINE bFEAT_FlagM #-}
bFEAT_FlagM :: Bool
bFEAT_FlagM = Bool
False

{-# INLINE bFEAT_FlagM2 #-}
bFEAT_FlagM2 :: Bool
bFEAT_FlagM2 = Bool
False

{-# INLINE bFEAT_FP16 #-}
bFEAT_FP16 :: Bool
bFEAT_FP16 = Bool
False

{-# INLINE bFEAT_FPAC #-}
bFEAT_FPAC :: Bool
bFEAT_FPAC = Bool
False

{-# INLINE bFEAT_FRINTTS #-}
bFEAT_FRINTTS :: Bool
bFEAT_FRINTTS = Bool
False

{-# INLINE bFEAT_I8MM #-}
bFEAT_I8MM :: Bool
bFEAT_I8MM = Bool
False

{-# INLINE bFEAT_JSCVT #-}
bFEAT_JSCVT :: Bool
bFEAT_JSCVT = Bool
False

{-# INLINE bFEAT_LRCPC #-}
bFEAT_LRCPC :: Bool
bFEAT_LRCPC = Bool
False

{-# INLINE bFEAT_LRCPC2 #-}
bFEAT_LRCPC2 :: Bool
bFEAT_LRCPC2 = Bool
False

{-# INLINE bFEAT_LSE #-}
bFEAT_LSE :: Bool
bFEAT_LSE = Bool
False

{-# INLINE bFEAT_LSE2 #-}
bFEAT_LSE2 :: Bool
bFEAT_LSE2 = Bool
False

{-# INLINE bFEAT_PAuth #-}
bFEAT_PAuth :: Bool
bFEAT_PAuth = Bool
False

{-# INLINE bFEAT_PAuth2 #-}
bFEAT_PAuth2 :: Bool
bFEAT_PAuth2 = Bool
False

{-# INLINE bFEAT_PMULL #-}
bFEAT_PMULL :: Bool
bFEAT_PMULL = Bool
False

{-# INLINE bFEAT_RDM #-}
bFEAT_RDM :: Bool
bFEAT_RDM = Bool
False

{-# INLINE bFEAT_RPRES #-}
bFEAT_RPRES :: Bool
bFEAT_RPRES = Bool
False

{-# INLINE bFEAT_SB #-}
bFEAT_SB :: Bool
bFEAT_SB = Bool
False

{-# INLINE bFEAT_SHA1 #-}
bFEAT_SHA1 :: Bool
bFEAT_SHA1 = Bool
False

{-# INLINE bFEAT_SHA256 #-}
bFEAT_SHA256 :: Bool
bFEAT_SHA256 = Bool
False

{-# INLINE bFEAT_SHA3 #-}
bFEAT_SHA3 :: Bool
bFEAT_SHA3 = Bool
False

{-# INLINE bFEAT_SHA512 #-}
bFEAT_SHA512 :: Bool
bFEAT_SHA512 = Bool
False

{-# INLINE bFEAT_SME #-}
bFEAT_SME :: Bool
bFEAT_SME = Bool
False

{-# INLINE bFEAT_SME_F64F64 #-}
bFEAT_SME_F64F64 :: Bool
bFEAT_SME_F64F64 = Bool
False

{-# INLINE bFEAT_SME_I16I64 #-}
bFEAT_SME_I16I64 :: Bool
bFEAT_SME_I16I64 = Bool
False

{-# INLINE bFEAT_SME2 #-}
bFEAT_SME2 :: Bool
bFEAT_SME2 = Bool
False

{-# INLINE bFEAT_SPECRES #-}
bFEAT_SPECRES :: Bool
bFEAT_SPECRES = Bool
False

{-# INLINE bFEAT_SSBS #-}
bFEAT_SSBS :: Bool
bFEAT_SSBS = Bool
False

{-# INLINE bFEAT_SVE #-}
bFEAT_SVE :: Bool
bFEAT_SVE = Bool
False

{-# INLINE bFEAT_SVE2 #-}
bFEAT_SVE2 :: Bool
bFEAT_SVE2 = Bool
False

{-# INLINE bFEAT_WFxT #-}
bFEAT_WFxT :: Bool
bFEAT_WFxT = Bool
False

#endif