module Language.Pck.Cpu.State (
EvalCpu
, CpuState
, pcFromCpuState
, grFromCpuState
, flFromCpuState
, imemFromCpuState
, dmemFromCpuState
, dumpCpuState
, initCpuState
, initCpuStateMem
, ResultStat(..)
, readPc
, updatePc
, incPc
, readGReg
, readGReg2
, updateGReg
, readFlags
, updateFlag
, fetchInst
, readDmem
, updateDmem
) where
import Control.Monad.State
import Language.Pck.Cpu.Config
import Language.Pck.Cpu.Instruction
import Language.Pck.Cpu.Register
import Language.Pck.Cpu.Memory
type EvalCpu a = State CpuState a
data ResultStat = RsNormal
| RsHalt
| RsDbgBrk
| RsErr String
deriving (Show, Eq)
data CpuState = CpuState
{ state_pc :: Int
, state_gr :: GRegArray
, state_fl :: FlagArray
, state_imem :: ImemArray
, state_dmem :: DmemArray
}
deriving Eq
pcFromCpuState :: CpuState -> Int
pcFromCpuState = state_pc
grFromCpuState :: CpuState -> [Int]
grFromCpuState = getGRegs . state_gr
flFromCpuState :: CpuState -> [Bool]
flFromCpuState = getFlags . state_fl
imemFromCpuState :: CpuState -> InstImage
imemFromCpuState = getInstImage . state_imem
dmemFromCpuState :: CpuState -> DataImage
dmemFromCpuState = getDataImage . state_dmem
instance Show CpuState where
show = showCpuState
showCpuState :: CpuState -> String
showCpuState s =
"pc : " ++ show (pcFromCpuState s) ++
"\ngr : " ++ show (grFromCpuState s) ++
"\nfl : " ++ show (flFromCpuState s) ++
"\nim : " ++ show (imemFromCpuState s) ++
"\ndm : " ++ show (dmemFromCpuState s) ++
"\n"
dumpCpuState :: CpuState -> String
dumpCpuState s =
"pc : " ++ show (pcFromCpuState s) ++
"\ngr : " ++ show (grFromCpuState s) ++
"\nfl : " ++ show (flFromCpuState s) ++
"\ndm : " ++ show (dmemFromCpuState s) ++
"\n"
initCpuState :: CpuState
initCpuState = CpuState
{ state_pc = cfgStartPc cpuConfig
, state_gr = initGReg
, state_fl = initFlag
, state_imem = initImem
, state_dmem = initDmem
}
initCpuStateMem :: InstImage -> DataImage -> CpuState
initCpuStateMem insts vals = initCpuState {state_imem = presetImem insts
,state_dmem = presetDmem vals}
readPc :: EvalCpu Int
readPc = gets state_pc
updatePc :: Int -> EvalCpu ResultStat
updatePc pc = do modify $ \s -> s { state_pc = pc }
return RsNormal
incPc :: EvalCpu ResultStat
incPc = do pc <- readPc
updatePc (pc + 1)
readGReg :: GReg -> EvalCpu Int
readGReg ra = do gr <- gets state_gr
return $ getGReg gr ra
readGReg2 :: GReg -> GReg -> EvalCpu (Int, Int)
readGReg2 ra rb = do gr <- gets state_gr
return (getGReg gr ra, getGReg gr rb)
updateGReg :: GReg -> Int -> EvalCpu ()
updateGReg reg val = do cpu <- get
let gr' = modifyGReg (state_gr cpu) reg val
put cpu { state_gr = gr' }
readFlags :: EvalCpu FlagArray
readFlags = gets state_fl
updateFlag :: Flag -> Bool -> EvalCpu ()
updateFlag flag val = do cpu <- get
let flags = state_fl cpu
fl' = modifyFlag flags flag val
put cpu { state_fl = fl' }
fetchInst :: EvalCpu Inst
fetchInst = do imem <- gets state_imem
pc <- readPc
return $ fetchImem imem pc
readDmem :: Int -> EvalCpu Int
readDmem ad = do cpu <- get
return $ getDmem (state_dmem cpu) ad
updateDmem :: Int -> Int -> EvalCpu ()
updateDmem ad val = do cpu <- get
let dmem' = modifyDmem (state_dmem cpu) ad val
put cpu { state_dmem = dmem' }