diff options
-rw-r--r-- | package.yaml | 1 | ||||
-rw-r--r-- | src/Commands.hs | 30 | ||||
-rw-r--r-- | src/Machine.hs | 38 | ||||
-rw-r--r-- | src/Suem.hs | 84 |
4 files changed, 101 insertions, 52 deletions
diff --git a/package.yaml b/package.yaml index 4894b86..73957e0 100644 --- a/package.yaml +++ b/package.yaml @@ -13,6 +13,7 @@ dependencies: - vector - bytestring - optparse-applicative +- lens library: source-dirs: src diff --git a/src/Commands.hs b/src/Commands.hs new file mode 100644 index 0000000..1413c87 --- /dev/null +++ b/src/Commands.hs @@ -0,0 +1,30 @@ +module Commands where + +import Control.Lens +import Machine + +doNothing :: Machine -> Machine +doNothing m = Machine (Registers (pc r + 2) (sr r) (drs r) + (ars r) (usp r) (ssp r)) + (ram m) (rom m) + where r = regs m + +doUnlink :: Int -> Machine -> Machine +doUnlink 7 m = let r = regs m in if isSupervisor m + then Machine (Registers (pc r + 2) (sr r) (drs r) (ars r) + (usp r) (getLong m (fromIntegral $ ssp r) + 4)) + (ram m) (rom m) + else Machine (Registers (pc r + 2) (sr r) (drs r) (ars r) + (getLong m (fromIntegral $ usp r) + 4) (ssp r)) + (ram m) (rom m) +doUnlink a m = let + r = regs m + av = getLong m (fromIntegral (ars r !! a)) + newars = ars r & element (fromIntegral a) .~ av + in if isSupervisor m + then Machine (Registers (pc r + 2) (sr r) (drs r) + newars (usp r) (av + 4)) + (ram m) (rom m) + else Machine (Registers (pc r + 2) (sr r) (drs r) + newars (av + 4) (ssp r)) + (ram m) (rom m) diff --git a/src/Machine.hs b/src/Machine.hs new file mode 100644 index 0000000..5e6256f --- /dev/null +++ b/src/Machine.hs @@ -0,0 +1,38 @@ +module Machine where + +import qualified Data.Vector.Unboxed as V +import Data.Word +import Data.Bits + +data Registers = Registers { + pc :: Word32, + sr :: Word16, + drs :: [Word32], -- d0 to d7 + ars :: [Word32], -- a0 to a6 + usp :: Word32, -- this is a7 in user mode + ssp :: Word32 -- this is a7 in supermode +} + +data Machine = Machine { + regs :: Registers, + ram :: V.Vector Word8, + rom :: V.Vector Word8 +} + +isSupervisor :: Machine -> Bool +isSupervisor m = testBit (sr $ regs m) 2 + +getByte :: Machine -> Int -> Word8 +getByte m a | a < 0x8 = rom m V.! a + | a < 0x7e0000 = if V.length (ram m) >= a then ram m V.! a + else 0xff + | a < 0x800000 = rom m V.! (a - 0x7e0000) + | otherwise = 0xff + +getWord :: Machine -> Int -> Word16 -- TODO: only even addresses are allowed +getWord m a = (fromIntegral $ getByte m a) * 256 + + (fromIntegral $ getByte m (a + 1)) + +getLong :: Machine -> Int -> Word32 -- TODO: only even addresses are allowed +getLong m a = (fromIntegral $ getWord m a) * 256 * 256 + + (fromIntegral $ getWord m (a + 2)) diff --git a/src/Suem.hs b/src/Suem.hs index 0602196..3ca635b 100644 --- a/src/Suem.hs +++ b/src/Suem.hs @@ -4,37 +4,8 @@ import qualified Data.Vector.Unboxed as V import qualified Data.ByteString as B import Data.Word import Data.Bits - - -data Registers = Registers { - pc :: Word32, - sr :: Word16, - drs :: [Word32], -- d0 to d7 - ars :: [Word32], -- a0 to a6 - usp :: Word32, -- this is a7 in user mode - ssp :: Word32 -- this is a7 in supermode -} - -data Machine = Machine { - regs :: Registers, - ram :: V.Vector Word8, - rom :: V.Vector Word8 -} - -getByte :: Machine -> Int -> Word8 -getByte m a | a < 0x8 = rom m V.! a - | a < 0x7e0000 = if V.length (ram m) >= a then ram m V.! a - else 0xff - | a < 0x800000 = rom m V.! (a - 0x7e0000) - | otherwise = 0xff - -getWord :: Machine -> Int -> Word16 -- TODO: only even addresses are allowed -getWord m a = (fromIntegral $ getByte m a) * 256 + - (fromIntegral $ getByte m (a + 1)) - -getLong :: Machine -> Int -> Word32 -- TODO: only even addresses are allowed -getLong m a = (fromIntegral $ getWord m a) * 256 * 256 + - (fromIntegral $ getWord m (a + 2)) +import Machine +import Commands data ConfigSocket = ConfigInet String | ConfigUnix String @@ -51,31 +22,40 @@ data Config = Config Int -- frequence (Maybe ConfigSocket) (Maybe ConfigSocket) -doCommand :: Word16 -> Machine -> Machine -doCommand cmd m = case cmd .&. 0xf000 of - 0 -> if testBit cmd 7 - then let rega = (shiftR cmd 9) .&. 0x7 in - m - else m - 0x1000 -> m - 0x2000 -> m - 0x3000 -> m - 0x4000 -> m - 0x5000 -> m - 0x6000 -> m - 0x7000 -> m - 0x8000 -> m - 0x9000 -> m - 0xb000 -> m - 0xc000 -> m - 0xd000 -> m - 0xe000 -> m - _ -> error "Bad command" +boolToInt :: Bool -> Int +boolToInt True = 1 +boolToInt False = 0 + +toBits :: Word16 -> [Int] +toBits x = map (boolToInt . testBit x) [0..(finiteBitSize x-1)] + +fromBits :: [Int] -> Int +fromBits = foldl (\a b -> 2 * a + b) 0 . reverse +doCommand :: [Int] -> Machine -> Machine +--doCommand [0,1,0,0,1,1,1,0, 0,1,1,0,0,0,0,0] = doReset +doCommand [0,1,0,0,1,1,1,0, 0,1,1,0,0,0,0,1] = doNothing +--doCommand [0,1,0,0,1,1,1,0, 0,1,1,0,0,0,1,0] = doStop +--doCommand [0,1,0,0,1,1,1,0, 0,1,1,0,0,0,1,1] = doRTE +--doCommand [0,1,0,0,1,1,1,0, 0,1,1,0,0,1,0,1] = doRTS +--doCommand [0,1,0,0,1,1,1,0, 0,1,1,0,0,1,1,0] = doTrapV +--doCommand [0,1,0,0,1,1,1,0, 0,1,1,0,0,1,1,1] = doRTR +--doCommand [0,1,0,0,1,0,1,0, 1,1,1,1,1,1,0,0] = doIllegal +--doCommand [0,1,0,0,1,0,1,0, 1,1,a,b,c,d,e,f] = +-- doTAS (fromBits [a,b,c]) (fromBits [d,e,f]) +--doCommand [0,1,0,0,1,0,1,0, a,b,c,d,e,f,g,h] = +-- doTST (fromBits [a,b]) (fromBits [c,d,e]) (fromBits [f,g,h]) +--doCommand [0,1,0,0,1,0,1,0, 0,1,0,0,a,b,c,d] = +-- doTrap (fromBits [a,b,c,d]) +--doCommand [0,1,0,0,1,0,1,0, 0,1,0,1,0,a,b,c] = +-- doLink (fromBits [a,b,c]) +doCommand [0,1,0,0,1,0,1,0, 0,1,0,1,1,a,b,c] = + doUnlink (fromBits [a,b,c]) +doCommand _ = error "Bad command." runMachine :: Machine -> IO () runMachine m = do - runMachine $ doCommand (getWord m $ fromIntegral $ pc $ regs m) m + runMachine $ doCommand (toBits $ getWord m $ fromIntegral $ pc $ regs m) m makeMachine :: V.Vector Word8 -> Int -> Machine makeMachine romData ramSize = Machine rs rd romData |