type Comment = String
data DTF =
- DTF_Data Address Value Code Label Comment |
- DTF_Instr Address Value Code Label Comment |
- DTF_Comment Comment |
- DTF_Label Label Comment Address |
+ DTF_Data Address Value Code Label Comment | -- 0;...
+ DTF_Instr Address Value Code Label Comment | -- 1;...
+ DTF_Comment Comment | -- 2;...
+ DTF_Label Label Comment Address | -- 3;...
-- types for intern processing
DTF_InstrToParse Address ValueToParse Code Label Comment |
DTF_SectionToDet Address Value Code Label Comment |
import Data.Word
import qualified Data.ByteString.Lazy as BL
import Control.Monad
--- import Data.Binary.Put
+
main :: IO ()
main = do
args <- getArgs
content <- getContents
let src = (filter (((/=) "") . snd) $ (zip [1..] (lines content)))
- let (dict,formatedsrc) = convertDTF src NoState 0x00 0x00 init_labels
- print args
- print formatedsrc
+ let (dict,formatedsrc) = convertDTF src NoState 0x00 0x00 []
+ printf "\nlabels:\n"
+ sequence_ [printf "%10s @ 0x%08x\n" l a | (l,a) <- (reverse dict)]
+ printf "\nparsed asm:\n"
+ sequence_ [printf "%s" (show x) | x <- formatedsrc]
-{-
- case runParser DT.parseInstructions () "stdin" src of
- Left err -> print err
- Right val -> do
- sequence_ [printf "0x%08X\n" x | x <- val]
--}
type Counter = Word32
inc = ((+) 4)
-type DictLabel = (String -> Word32)
+type DictLabel = (String,Word32)
-init_labels :: DictLabel
-init_labels _ = 0xffffffff
+get_label :: String -> [DictLabel] -> Maybe Word32
+get_label = lookup
-add_label :: DictLabel -> (String,Word32) -> DictLabel
+add_label :: [DictLabel] -> (String,Word32) -> [DictLabel]
add_label dic (s,w)
| s == "" = dic -- ignore empty string
- | dic s /= 0xffffffff = error ("Label " ++ s ++ " already exists")
- | otherwise = newdict
+ | already_in = error ("Label " ++ s ++ " already exists")
+ | otherwise = (s,w):dic
where
- newdict str
- | str == s = w
- | otherwise = dic str
+ already_in = case (get_label s dic) of
+ Just _ -> True
+ Nothing -> False
-convertDTF :: [(Int,String)] -> DT_State -> Counter -> Counter -> DictLabel -> (DictLabel, [DTF])
+convertDTF :: [(Int,String)] -> DT_State -> Counter -> Counter -> [DictLabel] -> ([DictLabel], [DTF])
convertDTF [] _ _ _ d = (d,[])
-convertDTF ((lno,str):xs) state datacnt instrcnt dict = (newdict, newdtf:next)
+convertDTF ((lno,str):xs) state datacnt instrcnt dict = (newdict, (actlist newdtf))
where
+ actlist (DTF_Org _) = next
+ actlist (DTF_State _) = next
+ actlist y = y:next
+
(newdict,next) = convertDTF xs (nstate newdtf) (ndatacnt newdtf) (ninstrcnt newdtf) (ndict newdtf)
ndatacnt (DTF_Org adr)
| state == InData = adr
| otherwise = datacnt
ndatacnt (DTF_Data _ _ _ _ _) = inc datacnt
+ ndatacnt _ = datacnt
ninstrcnt (DTF_Org adr)
| state == InText = adr
| otherwise = instrcnt
ninstrcnt (DTF_Instr _ _ _ _ _) = inc instrcnt
+ ninstrcnt (DTF_InstrToParse _ _ _ _ _) = inc instrcnt
+ ninstrcnt _ = instrcnt
nstate (DTF_State s) = s
nstate _ = state
ndict (DTF_InstrToParse a _ _ l _) = dict `add_label` (l,a)
ndict (DTF_Data a _ _ l _) = dict `add_label` (l,a)
ndict (DTF_Instr a _ _ l _) = dict `add_label` (l,a)
+ ndict _ = dict
newdtf = case (parse parseDTFLine "" (str++"\n")) of
- Left err -> error "couldn't parse line " ++ (show lno) ++ ": " ++ (show err)
+ Left err -> error ("couldn't parse line " ++ (show lno) ++ ": " ++ (show err))
Right (DTF_SectionToDet _ v c l s) ->
case state of
NoState -> error "missing .data or .text"
parseConst = do
skipMany space
-- TODO: only decimal and hex (since this is supported by read)
- -- TODO: how to check to big values?
+ -- TODO: howto check too big values? atm they get truncated
str <- try(do pref <- string "0x"; z <- many1 hexDigit; return $ (pref ++ z)) <|> (many1 digit)
let val = read str
return $ val
-zwei durchlaeufe:
+Beschreibung:
-(1) zeilen in das programmer format umwandeln, d.h.
-bis auf value werden eigentlich schon alle saplten aufgeloest. gleichzeitig wird
-eine tabelle mit labels und deren adresse aufgebaut (zwei tabellen fuer
-instr und data mem noetig)
+Der Parser braucht zwei Durchlaeufe. Der erste Durchlauf loest z.b. Labels auf
+und kuemmert sich darum welche Daten nach .data und welche nach .text gehoeren.
+Im zweiten Durchlauf werden die eigentlichen Instructions geparst und den
+entsprechenden Bytecode umgewandelt. Da zu diesem Zeitpunkt Labels und Defines
+schon in einer Datenstruktur vorhanden sind, sollte bezueglich
+Adressenaufloesung nicht mehr viel schief gehen.
-ausserdem:
-- auf .data und .text achten
-- .include
-- .org
-- .fill aufloesen
-- .define tabelle
-@hi und @lo behandeln?
+(1) Aufgaben der first Stage:
-(2) value das noch als string vorhanden ist, wird als instruction geparst.
+- .data <- done (wenn man nett ist, springt man nicht lustig zwischen diesen
+- .text <- done (sections hin und her... es *sollte* zwar gehen, aber [...] :p)
+- .include <- TODO: zu umstaendlich? :/ Mal schaun ob mir eine einfache Loesung
+ einfaellt.
+- .org <- done
+- .fill aufloesen <- TODO: atm nur einmalig 32bit moeglich
+- .define tabelle <- TODO
+
+- @hi und @lo behandeln? <- TODO: doch eher second stage
+
+
+(2) Values die noch als String vorhanden ist, werden als instruction geparst.
+ (vgl. 3. Spalte der 'itp;...' Ausgaben). second stage = BIG TODO
+
+
+einschraenkungen atm:
+- gleicher Namensraum fuer labels in .text und .data! wenn einer ein Label aus
+ .data laedt und dann aber eigentlich auf .text zugreift ist er selber schuld :/
+- viele viele mehr *testbench schreiben muss*