diff options
Diffstat (limited to 'compiler.hs')
| -rw-r--r-- | compiler.hs | 55 | 
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 =  | 
