crucible-llvm-0.6: src/Lang/Crucible/LLVM/Arch/X86.hs
{-# Language GADTs #-}
{-# Language DataKinds #-}
{-# Language KindSignatures #-}
{-# Language TypeOperators #-}
{-# Language ExplicitNamespaces #-}
{-# Language TemplateHaskell #-}
{-# Language RankNTypes #-}
{-# Language ScopedTypeVariables #-}
{-# Language PatternGuards #-}
{-# Language MultiWayIf #-}
module Lang.Crucible.LLVM.Arch.X86 where
import qualified Data.BitVector.Sized as BV
import Data.Word(Word8)
import Data.Bits
import Data.Kind
import GHC.TypeNats (type (<=))
import Data.Parameterized.NatRepr(knownNat)
import Data.Parameterized.Classes(testEquality,compareF)
import Data.Parameterized.TraversableFC
import Data.Parameterized.TH.GADT as U
import What4.Interface (SymBV)
import qualified What4.Interface as I
import Lang.Crucible.CFG.Extension
import Lang.Crucible.Types(CrucibleType,BVType,NatRepr,TypeRepr(..))
import Lang.Crucible.Simulator.RegValue(RegValue)
import Lang.Crucible.Panic(panic)
import Lang.Crucible.LLVM.Arch.Util((|->))
data AVXOp1 = VShiftL Word8 -- ^ Shift left by this many bytes
-- New bytes are 0.
| VShufD Word8 -- ^ Shuffle 32-bit words of vector
-- according to pattern in the word8
deriving (Eq,Ord)
data ExtX86 :: (CrucibleType -> Type) -> CrucibleType -> Type where
{- | Unary operation on a vector. Should have no side effects. -}
VOp1 :: (1 <= n) =>
!(NatRepr n) -> {- width of input/result -}
!AVXOp1 -> {- do this operation -}
!(f (BVType n)) -> {- on this thing -}
ExtX86 f (BVType n)
eval :: forall sym f tp.
I.IsSymExprBuilder sym =>
sym ->
(forall subT. f subT -> IO (RegValue sym subT)) ->
ExtX86 f tp ->
IO (RegValue sym tp)
eval sym ev ext =
case ext of
VOp1 w op e ->
case op of
VShiftL amt -> vShiftL sym w amt =<< ev e
VShufD ixes -> vShufD sym w ixes =<< ev e
-- | See @vpslldq@
vShiftL :: (I.IsSymExprBuilder sym, 1 <= w) =>
sym -> NatRepr w -> Word8 -> SymBV sym w -> IO (SymBV sym w)
vShiftL sym w amt v =
do i <- I.bvLit sym w (BV.mkBV w (8 * fromIntegral amt))
I.bvShl sym v i
-- | See @vpshufd@
vShufD :: forall sym w.
I.IsSymExprBuilder sym =>
sym -> NatRepr w -> Word8 -> SymBV sym w -> IO (SymBV sym w)
vShufD sym w ixes v
| Just I.Refl <- testEquality w n128 = mk128 v
| Just I.Refl <- testEquality w n256 =
do lower128 <- mk128 =<< I.bvSelect sym n0 n128 v
upper128 <- mk128 =<< I.bvSelect sym n128 n128 v
I.bvConcat sym upper128 lower128
| otherwise = panic "Arch.X86.vShufD"
[ "*** Unexpected width: " ++ show (I.natValue w) ]
where
mk128 :: SymBV sym 128 -> IO (SymBV sym 128)
mk128 src = do f0 <- getV src 0
f1 <- getV src 1
f2 <- getV src 2
f3 <- getV src 3
lower64 <- I.bvConcat sym f1 f0
upper64 <- I.bvConcat sym f3 f2
I.bvConcat sym upper64 lower64
getV :: SymBV sym 128 -> Int -> IO (SymBV sym 32)
getV src n = case getIx n of
0 -> I.bvSelect sym n0 n32 src
1 -> I.bvSelect sym n1 n32 src
2 -> I.bvSelect sym n2 n32 src
_ -> I.bvSelect sym n3 n32 src
getIx :: Int -> Word8
getIx n = (ixes `shiftR` (2 * n)) .&. 0x03 -- get 2 bit field
--------------------------------------------------------------------------------
n0 :: NatRepr 0
n0 = knownNat
n1 :: NatRepr 1
n1 = knownNat
n2 :: NatRepr 2
n2 = knownNat
n3 :: NatRepr 3
n3 = knownNat
n32 :: NatRepr 32
n32 = knownNat
n128 :: NatRepr 128
n128 = knownNat
n256 :: NatRepr 256
n256 = knownNat
--------------------------------------------------------------------------------
$([d| {- New TH Scope -} |])
-- This is going to go away
instance ShowFC ExtX86 where
showFC _ _ = error "[ShowFC ExtX86] Not implmented."
instance TestEqualityFC ExtX86 where
testEqualityFC testSubterm =
$(U.structuralTypeEquality [t| ExtX86 |]
[ U.ConType [t|NatRepr |] `U.TypeApp` U.AnyType |-> [|testEquality|]
, U.DataArg 0 `U.TypeApp` U.AnyType |-> [|testSubterm|]
])
instance OrdFC ExtX86 where
compareFC testSubterm =
$(U.structuralTypeOrd [t| ExtX86 |]
[ U.ConType [t|NatRepr |] `U.TypeApp` U.AnyType |-> [|compareF|]
, U.DataArg 0 `U.TypeApp` U.AnyType |-> [|testSubterm|]
])
-- This is going away
instance HashableFC ExtX86 where
hashWithSaltFC _hash _s _x = error "[HashableFC ExtX86] Not implmented."
instance FunctorFC ExtX86 where
fmapFC = fmapFCDefault
instance FoldableFC ExtX86 where
foldMapFC = foldMapFCDefault
instance TraversableFC ExtX86 where
traverseFC = $(U.structuralTraversal [t|ExtX86|] [])
instance PrettyApp ExtX86 where
ppApp _pp _x = error "[PrettyApp ExtX86] XXX"
instance TypeApp ExtX86 where
appType x =
case x of
VOp1 w _ _ -> BVRepr w