libriscv-0.1.0.0: lib/LibRISCV/Effects/Decoding/Default/Interpreter.hs
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
-- | Provides the default (concrete) interpretation for the decoding effect. This
-- implementation assumes that the 'Decodable' type class can be implemented for
-- the underlying type parameter, that is, it must be possible to convert the
-- type to a fixed-width concrete integer.
module LibRISCV.Effects.Decoding.Default.Interpreter where
import Control.Monad.Freer (type (~>))
import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.BitVector (BV, bitVec)
import Data.Data (Proxy (..))
import Data.IORef (IORef, readIORef, writeIORef)
import Data.Word (Word32)
import LibRISCV.Effects.Decoding.Language (Decoding (..))
import LibRISCV.Internal.Decoder.Instruction (immB, immI, immJ, immS, immU, mkRd, mkRs1, mkRs2, mkShamt)
import LibRISCV.Internal.Decoder.Opcodes (decode)
-- | Decoder state used to implement the stateful 'SetInstr' constructor of the 'Decoding' effect.
type DecoderState = IORef Word32
-- | Type class used to perform conversion from/to a fixed-with concrete integer.
class Decodable a where
fromWord :: Word32 -> a
-- ^ Convert from a fixed-with integer to the underlying value type of the interpreter.
toWord :: a -> Word32
-- ^ Convert from the underlying value type to a fixed-with integer.
instance Decodable BV where
fromWord = bitVec 32
toWord = fromIntegral
-- | Concrete implementation of the decoding effect.
defaultDecoding :: forall v m. (Decodable v, MonadIO m) => DecoderState -> Decoding v ~> m
defaultDecoding instRef =
let
decodeAndConvert f = fmap (fromWord . f) . readIORef
in
liftIO . \case
SetInstr v -> writeIORef instRef $ toWord v
WithInstrType Proxy f -> f . decode <$> readIORef instRef
DecodeRD -> decodeAndConvert mkRd instRef
DecodeRS1 -> decodeAndConvert mkRs1 instRef
DecodeRS2 -> decodeAndConvert mkRs2 instRef
DecodeImmI -> decodeAndConvert immI instRef
DecodeImmS -> decodeAndConvert immS instRef
DecodeImmB -> decodeAndConvert immB instRef
DecodeImmU -> decodeAndConvert immU instRef
DecodeImmJ -> decodeAndConvert immJ instRef
DecodeShamt -> decodeAndConvert mkShamt instRef