diff --git a/.gitignore b/.gitignore index 910b4cf..ff4fab1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ main-c main-hs *.hi *.o +ladirvirelyl-hs +xarzniar-hs diff --git a/assembler/CommonIO.hs b/assembler/CommonIO.hs new file mode 100644 index 0000000..92a5faa --- /dev/null +++ b/assembler/CommonIO.hs @@ -0,0 +1,30 @@ +{-# OPTIONS -Wall -fno-warn-unused-do-bind #-} +module CommonIO +(semicolonExtension +,parse' +,(>>>=) +) where +import System.IO +--import System.Environment(getArgs) +--import Control.Monad +--import Data.List + +import Parse +--import Execute +--import Linker +import Messages +import Types + + +semicolonExtension :: String -> String +semicolonExtension = unlines . map (takeWhile (/=';')) . lines + +parse' :: FilePath -> IO () +parse' filepath = do + str <- semicolonExtension <$> readFile filepath + putStrLn' English $ NormalMessage $ "\nparsing " ++ filepath ++ ":\n" + fullParse' str >>>= print + +(>>>=) :: (Message a) => Either a b -> (b -> IO ()) -> IO () +Right b >>>= action = action b +Left a >>>= _ = hPutStrLn stderr (show' English a) diff --git a/assembler/Makefile b/assembler/Makefile index bc3301d..8b14aeb 100644 --- a/assembler/Makefile +++ b/assembler/Makefile @@ -1,7 +1,8 @@ .PHONY: c haskell haskell: - ghc main.hs -o main-hs -Wall + ghc xarzniar.hs -o xarzniar-hs -Wall + ghc ladirvirelyl.hs -o ladirvirelyl-hs -Wall c: gcc main.c parse.c -o main-c diff --git a/assembler/ladirvirelyl.hs b/assembler/ladirvirelyl.hs new file mode 100644 index 0000000..417fb20 --- /dev/null +++ b/assembler/ladirvirelyl.hs @@ -0,0 +1,28 @@ +{-# OPTIONS -Wall -fno-warn-unused-do-bind #-} +-- import System.IO +import System.Environment(getArgs) +import Control.Monad +import Data.List + +-- import Parse +-- import Execute +-- import Linker +import Messages +import Types +import CommonIO + + +main :: IO () +main = do + args <- getArgs + main'' args + +main'' :: [FilePath] -> IO () +main'' paths = do + mapM_ parse' paths + strs <- forM paths (fmap semicolonExtension . readFile) + putStrLn' English $ NormalMessage $ "\ncompiling " ++ intercalate ", " paths ++ ":\n" + fullCompile' strs + +fullCompile' :: [String] -> IO () +fullCompile' strs = undefined diff --git a/assembler/main.hs b/assembler/xarzniar.hs similarity index 82% rename from assembler/main.hs rename to assembler/xarzniar.hs index 2052a81..48d7fad 100644 --- a/assembler/main.hs +++ b/assembler/xarzniar.hs @@ -9,13 +9,12 @@ import Execute import Linker import Messages import Types +import CommonIO -semicolonExtension :: String -> String -semicolonExtension = unlines . map (takeWhile (/=';')) . lines - +{- fullExecute :: String -> IO () fullExecute = fullExecute' . return - +-} fullExecute' :: [String] -> IO () fullExecute' strs = strs `getProgramAndApply` \program -> let (boolerh, logs) = execute program in do @@ -26,9 +25,7 @@ fullExecute' strs = strs `getProgramAndApply` \program -> getProgramAndApply :: [String] -> (Program -> IO ()) -> IO () strs `getProgramAndApply` f = mapM fullParse' strs >>>= \ps -> linker ps >>>= f -(>>>=) :: (Message a) => Either a b -> (b -> IO ()) -> IO () -Right b >>>= action = action b -Left a >>>= _ = hPutStrLn stderr (show' English a) + main :: IO () main = do @@ -66,15 +63,10 @@ main'' paths = do strs <- forM paths (fmap semicolonExtension . readFile) putStrLn' English $ NormalMessage $ "\nrunning " ++ intercalate ", " paths ++ ":\n" fullExecute' strs - +{- main' :: FilePath -> IO () main' filepath = main'' [filepath] - -parse' :: FilePath -> IO () -parse' filepath = do - str <- semicolonExtension <$> readFile filepath - putStrLn' English $ NormalMessage $ "\nparsing " ++ filepath ++ ":\n" - fullParse' str >>>= print +-} demo :: IO () diff --git a/opcode.html b/opcode.html index b92cd05..fc5af5a 100644 --- a/opcode.html +++ b/opcode.html @@ -1832,6 +1832,117 @@

46. エントリーポイント

よさそう。

+

47. オペコードなどについて考察する

+

そろそろオペコードやっていきましょうか。

+

「データへのアクセスは32bit固定長なのになんで命令は8bit単位なのか」などという突っ込みどころが存在するが、まあ気にせずやっていきましょう。

+

とりあえず、前に炭酸ソーダさんが作ってくださったを見てみよう。

+
+8ビットを基本とした可変長セット
+回路設計が簡単になるように考慮
+'i'c順を基にする
+
+命令の構成
+00oooooo 命令 o:OPCODE
+rrrmmmmm 1つめのオペランド。MODEがimmの場合REGは無視される。r:REG m:MODE
+(imm/disp)
+rrrmmmmm 2つめのオペランド
+(imm/disp)
+(rrrmmmmm 3つめのオペランド)
+(imm/disp)
+
+OPCODE
+0xxxxx: オペランド2つの命令
+000000: ata +
+000001: nta -
+000010: ada &
+000011: ekc |
+000100: dto >>>
+000101: dro <<
+000110: dtosna >>
+000111: dal ~^
+001000: krz =
+001001: malkrz
+01cccc: fi
+10xxxx: オペランド3つの命令
+100000: inj
+101000: lat
+101001: latsna
+
+COND
+0000 llonys >
+0001 xtlonys <=
+0010 xolonys >=
+0011 xylonys <
+0110 clo ==
+0111 niv !=
+1000 llo >
+1001 xtlo <=
+1010 xolo >=
+1011 xylo <
+比較は 右の値 + (-左の値) で行う。順番が逆なのはntaに合わせるため
+上記ビットをscznに割り当てる
+Z: 加算の結果が0かどうか
+C: 加算で最上位ビットで繰り上がりが起きて捨てられたか
+判定は、((z AND Z) OR NOT(c OR C)) XOR n で決定する
+sが1の場合は比較処理の前に両方の値の最上位ビットを反転さそる
+
+REG
+000: f0
+001: f1
+010: f2
+011: f3
+101: f5
+111: xx
+
+MODE
+00000: reg
+00100: imm8
+00101: imm16
+00110: imm32
+10000: reg@
+10100: reg+disp8@
+10101: reg+disp16@
+10110: reg+disp32@
+11rrr: reg+reg@ r:2つめのreg
+immかdispを含むとき、その値を表す8/16/32ビットの値が後続する。
+imm8/16は符号無し、disp8/16符号あり(C0ならFFFFFFC0として扱う)
+
+
+例
+'c'i
+nll fib1
+krz f0 f5+ 4@
+krz f1 0
+krz f2 1
+fi f0 0 clo l' is malkrz xx ka
+nta f0 1
+krz f3 f1
+ata f3 f2
+inj f1 f2 f3
+krz xx is
+krz f0 f1 l' ka
+krz xx f5@
+
+1482E8D4: 08 B4 04 00
+1482E8D8: 08 04 00 20
+1482E8DC: 08 04 01 40
+1482E8E0: 16 00 04 00
+1482E8E4: 09 06 14 82 E8 FC E0
+1482E8EB: 01 04 01 00
+1482E8EF: 08 20 60
+1482E8F2: 00 40 60
+1482E8F5: 20 60 40 20
+1482E8F5: 08 06 14 82 E8 E0 E0
+1482E8FC: 08 20 00
+1482E8FF: 08 B0 E0
+
+

とのこと。

+

よさそう(よさそう)

+

とりあえずアセンブラでも考えてみるか?Haskellに触れるのは大分久しぶりだな。

+

インタプリタの方をxarzniarと改名し、ladirvirelyl.hsというファイルを新たに作成。

+

共通化できそうな処理はCommonIO.hsとして分離し、とりあえず形式だけ合わせたダミーを作成。

+

さて、まともなコンパイラとリンカを作らねばなぁ。nヶ月前に書いたコードだからどういう構成になってるのかも読み返さねばだし。

+

xxx. To do

xxx-1. 割り算