summaryrefslogtreecommitdiff
path: root/compiler.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler.hs')
-rw-r--r--compiler.hs55
1 files changed, 26 insertions, 29 deletions
diff --git a/compiler.hs b/compiler.hs
index 8a98a2d..eab7058 100644
--- a/compiler.hs
+++ b/compiler.hs
@@ -36,51 +36,48 @@ compile (Program inss) = runLineWriter $ do
mapM_ compileIns inss
emit0 epilogue
-cursor :: String
-cursor = "rbx"
+cursorReg :: String
+cursorReg = "rbx"
+
+cursorOffset :: Offset -> String
+cursorOffset 0 = cursorReg
+cursorOffset off = cursorReg ++ " + " ++ show off
compileIns :: Instruction -> LineWriter ()
-compileIns (IAdd v off) = emit $ "add byte [" ++ cursor ++ " + " ++ show off ++ "], " ++ show v
-compileIns (ISet v off) = emit $ "mov byte [" ++ cursor ++ " + " ++ show off ++ "], " ++ show v
-compileIns (IMove from []) = do
- emit $ "mov byte [" ++ cursor ++ " + " ++ show from ++ "], 0"
-compileIns (IMove from [(o,m)]) = do
- emit $ "mov al, [" ++ cursor ++ " + " ++ show from ++ "]"
- if m == 1 then return ()
- else do
- emit $ "mov cl, " ++ show m
- emit "mul byte cl"
- emit $ "add [" ++ cursor ++ " + " ++ show o ++ "], al"
- emit $ "mov byte [" ++ cursor ++ " + " ++ show from ++ "], 0"
-compileIns (IMove from tos) = do
- emit $ "mov dl, [" ++ cursor ++ " + " ++ show from ++ "]"
- emit $ "mov byte [" ++ cursor ++ " + " ++ show from ++ "], 0"
- forM_ tos $ \(o,m) -> do
- emit "mov al, dl"
- if m == 1 then return ()
- else do
- emit $ "mov cl, " ++ show m
- emit "mul byte cl"
- emit $ "add [" ++ cursor ++ " + " ++ show o ++ "], al"
-compileIns (ISlide off) = emit $ "add " ++ cursor ++ ", " ++ show off
+compileIns (IAdd v off) = emit $ "add byte [" ++ cursorOffset off ++ "], " ++ show v
+compileIns (ISet v off) = emit $ "mov byte [" ++ cursorOffset off ++ "], " ++ show v
+compileIns (ICopy _ _ 0) = return ()
+compileIns (ICopy from to m) = do
+ emit $ "mov al, [" ++ cursorOffset from ++ "]"
+ case m of
+ 1 -> return ()
+ _ | Just p <- isTwoPower m -> emit $ "shl al, " ++ show p
+ | otherwise -> do
+ emit $ "mov cl, " ++ show m
+ emit "mul byte cl"
+ emit $ "add [" ++ cursorOffset to ++ "], al"
+compileIns (ISlide off) = emit $ "add " ++ cursorReg ++ ", " ++ show off
compileIns (ILoop inss off) = do
loopid <- genId
- emit $ "cmp byte [" ++ cursor ++ " + " ++ show off ++ "], 0"
+ emit $ "cmp byte [" ++ cursorOffset off ++ "], 0"
emit $ "jz .Laf_" ++ show loopid
emit0 $ ".Lbd_" ++ show loopid ++ ":"
mapM_ compileIns inss
- emit $ "cmp byte [" ++ cursor ++ " + " ++ show off ++ "], 0"
+ emit $ "cmp byte [" ++ cursorOffset off ++ "], 0"
emit $ "jnz .Lbd_" ++ show loopid
emit0 $ ".Laf_" ++ show loopid ++ ":"
compileIns (IInput off) = do
emit "call _getchar"
- emit $ "mov [" ++ cursor ++ " + " ++ show off ++ "], al"
+ emit $ "mov [" ++ cursorOffset off ++ "], al"
compileIns (IOutput off) = do
emit "xor edi, edi"
- emit $ "mov dil, [" ++ cursor ++ " + " ++ show off ++ "]"
+ emit $ "mov dil, [" ++ cursorOffset off ++ "]"
emit "call _putchar"
compileIns IStart = return ()
+isTwoPower :: Byte -> Maybe Int
+isTwoPower v = findIndex (==v) (take 8 $ iterate (* 2) 1)
+
prologue :: String
prologue =