data Reg = Zero | At | V0 | V1
| A0 | A1 | A2 | A3
| T0 | T1 | T2 | T3 | T4 | T5 | T6 | T7
| S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7
| T8 | T9
| GP | SP | FP | RQ
| PC
deriving (Eq, Ord, Show, Enum, Bounded)
data Insn = Add Reg Reg Reg
| Sub Reg Reg Reg
| J Word
deriving (Eq, Ord, Show)
data PseudoInsn = Pseudo [Insn]
data Cell = W Word | I Insn deriving (Eq, Ord, Show)
data VM = VM (Map.Map Reg Cell) (Map.Map Word Cell) deriving (Eq, Show)
readReg r = gets $ \ (VM rs cs) -> fromMaybe err (Map.lookup r rs)
where err = error $ "Invalid Register: " ++ show r
readMem a = gets $ \ (VM rs cs) -> fromMaybe err (Map.lookup a cs)
where err = error $ "Invalid Address: " ++ show a
writeReg r x = modify $ \ (VM rs cs) -> VM (Map.insert r x rs) cs
writeMem a x = modify $ \ (VM rs cs) -> VM rs (Map.insert a x cs)
incr r = do
W x <- readReg r
writeReg r (W (x + 1))
fetch :: MonadState VM m => m Cell
fetch = do
W pc <- readReg PC
readMem pc
decode :: Cell -> Insn
decode (I x) = x
decode _ = error "Invalid Instruction"
exec :: MonadState VM m => m ()
exec = do
op <- fetch
case decode op of
Add rs rt rd -> do
W s <- readReg rs
W t <- readReg rt
writeReg rd (W (s + t))
incr PC
exec