module Arm.Swi
where
import Data.Bits
import Data.Char
import Data.IORef
import Data.Word
import Arm.CPU
import Arm.Loader
import Arm.Memory
import Arm.Register
import Arm.RegisterName
line = "----------------------------------------"
swi
:: CPU
-> Word32
-> Bool
-> IO ()
swi cpu 0 debug
= do let regs = registers cpu
r0 <- getReg regs R0
let c = fromIntegral r0
if debug
then do putStrLn line
putStrLn ("CHR: [" ++ [chr c] ++ "]")
putStrLn line
else putStr [chr c]
swi cpu 1 debug
= do let regs = registers cpu
r0 <- getReg regs R0
let r0i = fromIntegral r0
if debug
then do putStrLn line
putStrLn ("INT: [" ++ show r0i ++ "]")
putStrLn line
else putStr (show r0i)
swi cpu 2 debug
= do let regs = registers cpu
r0 <- getReg regs R0
str <- fetchString (memory cpu) r0
if debug
then do putStrLn line
putStrLn ("STR: [" ++ str ++ "]")
putStrLn line
else putStr str
swi cpu 3 debug
= do if debug
then do putStrLn line
putStr "INPUT INT: "
else return ()
i <- readLn
if debug
then putStrLn line
else return ()
let w = fromIntegral i
let regs = registers cpu
setReg regs R0 w
swi cpu 4 debug
= do if debug
then do putStrLn line
putStr "INPUT STRING: "
else return ()
s <- getLine
if debug
then putStrLn s
else return ()
let regs = registers cpu
addr <- getReg regs R0
r1 <- getReg regs R1
let len = fromIntegral r1
let s' = take (len 1) s
let mem = memory cpu
loadString mem addr (s' ++ ['\NUL'])
swi cpu 10 debug
= do if debug
then do putStrLn line
putStrLn "NEWLINE"
putStrLn line
else putStrLn ""
swi cpu 11 debug
= do if debug
then do putStrLn line
putStrLn "NORMAL EXIT"
putStrLn line
else return ()
let runFlag = running cpu
writeIORef runFlag False
swi cpu a debug = error $ "unknown SWI: " ++ show a ++ " " ++ show debug
fetchString
:: Memory
-> Address
-> IO String
fetchString mem addr
= do word <- readMem mem addr
let c4 = fromIntegral ((word .&. 0xFF000000) `shift` (24))
let c3 = fromIntegral ((word .&. 0xFF0000) `shift` (16))
let c2 = fromIntegral ((word .&. 0xFF00) `shift` (8))
let c1 = fromIntegral (word .&. 0xFF)
if c1 == 0
then return ""
else if c2 == 0
then return [chr c1]
else if c3 == 0
then return [chr c1, chr c2]
else if c4 == 0
then return [chr c1, chr c2, chr c3]
else do s <- fetchString mem (addr + 4)
return ([chr c1, chr c2, chr c3, chr c4] ++ s)