packages feed

libriscv-0.1.0.0: app/Main.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}

module Main where

import Control.Monad (when)
import Control.Monad.Freer
import Data.BitVector
import Data.IORef (newIORef)
import Data.Word (Word32)
import LibRISCV (RegIdx (SP), align)
import LibRISCV.CmdLine
import LibRISCV.Effects.Decoding.Default.Interpreter (
    defaultDecoding,
 )
import LibRISCV.Effects.Expressions.Default.Interpreter (defaultEval, evalE)
import qualified LibRISCV.Effects.Expressions.Expr as E
import LibRISCV.Effects.Logging.Default.Interpreter (
    defaultLogging,
    noLogging,
 )
import LibRISCV.Effects.Operations.Default.Interpreter (
    defaultInstructions,
    dumpState,
    getMem,
    mkArchState,
 )
import LibRISCV.Effects.Operations.Default.Machine.Memory (storeByteString)
import LibRISCV.Loader
import LibRISCV.Semantics (buildAST, writeRegister)
import Options.Applicative

main' :: BasicArgs -> IO ()
main' (BasicArgs memAddr memSize trace putReg fp) = do
    state <- mkArchState memAddr memSize

    elf <- readElf fp
    loadElf elf $ storeByteString fromIntegral (getMem state)
    entry <- startAddr elf

    instRef <- newIORef (0 :: Word32)
    let
        initalSP = align (memAddr + memSize - 1)
        evalEnv = ((== 1), evalE)
        interpreter =
            interpretM (defaultInstructions state)
                . interpretM (defaultEval evalEnv)
                . interpretM (defaultDecoding @BV instRef)
                . interpretM (if trace then defaultLogging else noLogging)
    runM $ interpreter $ do
        writeRegister (bitVec 32 $ fromEnum SP) (E.FromInt 32 $ fromIntegral initalSP)
        buildAST @32 (bitVec 32 entry)

    when putReg $
        dumpState state

main :: IO ()
main = main' =<< execParser opts
  where
    opts =
        info
            (basicArgs <**> helper)
            ( fullDesc
                <> progDesc "Concrete execution of RV32I machine code"
            )