Format and parse instructions with optional arguments correctly

This also fixes parsing of instructions with arguments
This commit is contained in:
Joscha 2019-11-26 08:39:42 +00:00
parent d082bc939e
commit 6712a9c32c
3 changed files with 40 additions and 14 deletions

View file

@ -28,4 +28,7 @@ formatLargeOpcode = T.pack . show
formatInstruction :: Instruction -> T.Text formatInstruction :: Instruction -> T.Text
formatInstruction (SmallInstruction so lv) = formatSmallOpcode so <> " " <> formatLargeValue lv formatInstruction (SmallInstruction so lv) = formatSmallOpcode so <> " " <> formatLargeValue lv
formatInstruction (LargeInstruction lo sv) = formatLargeOpcode lo <> " " <> formatSmallValue sv formatInstruction (LargeInstruction lo sv) =
if argumentIsOptional lo && sv == 0
then formatLargeOpcode lo
else formatLargeOpcode lo <> " " <> formatSmallValue sv

View file

@ -3,6 +3,7 @@
module Mima.Instruction module Mima.Instruction
( SmallOpcode(..) ( SmallOpcode(..)
, LargeOpcode(..) , LargeOpcode(..)
, argumentIsOptional
, Instruction(..) , Instruction(..)
, wordToInstruction , wordToInstruction
, instructionToWord , instructionToWord
@ -75,6 +76,22 @@ largeOpcodeNr STRF = 13
largeOpcodeMap :: Map.Map Opcode LargeOpcode largeOpcodeMap :: Map.Map Opcode LargeOpcode
largeOpcodeMap = Map.fromList [(largeOpcodeNr lo, lo) | lo <- allLargeOpcodes] largeOpcodeMap = Map.fromList [(largeOpcodeNr lo, lo) | lo <- allLargeOpcodes]
argumentIsOptional :: LargeOpcode -> Bool
argumentIsOptional HALT = True
argumentIsOptional NOT = True
argumentIsOptional RAR = True
argumentIsOptional RET = True
argumentIsOptional LDRA = True
argumentIsOptional STRA = True
argumentIsOptional LDSP = True
argumentIsOptional STSP = True
argumentIsOptional LDFP = True
argumentIsOptional STFP = True
argumentIsOptional LDRS = False
argumentIsOptional STRS = False
argumentIsOptional LDRF = False
argumentIsOptional STRF = False
data Instruction data Instruction
= SmallInstruction !SmallOpcode !LargeValue = SmallInstruction !SmallOpcode !LargeValue
| LargeInstruction !LargeOpcode !SmallValue | LargeInstruction !LargeOpcode !SmallValue

View file

@ -6,8 +6,10 @@ module Mima.Parse.Assembly.RawInstruction
, cookInstruction , cookInstruction
) where ) where
import Control.Monad
import qualified Data.Text as T import qualified Data.Text as T
import Text.Megaparsec import Text.Megaparsec
import qualified Text.Megaparsec.Char as C
import Mima.Instruction import Mima.Instruction
import Mima.Parse.Assembly.Common import Mima.Parse.Assembly.Common
@ -21,7 +23,7 @@ data RawInstruction a
deriving (Show) deriving (Show)
parseByName :: [(T.Text, a)] -> Parser a parseByName :: [(T.Text, a)] -> Parser a
parseByName = foldl (<|>) empty . map (\(name, a) -> a <$ symbol' name) parseByName = foldl (<|>) empty . map (\(name, a) -> a <$ C.string' name)
smallOpcode :: Parser SmallOpcode smallOpcode :: Parser SmallOpcode
smallOpcode = parseByName smallOpcode = parseByName
@ -53,25 +55,29 @@ largeOpcode = parseByName
, ("stsp", STSP) , ("stsp", STSP)
, ("ldfp", LDFP) , ("ldfp", LDFP)
, ("stfp", STFP) , ("stfp", STFP)
] , ("ldrs", LDRS)
largeOpcodeWithArgument :: Parser LargeOpcode
largeOpcodeWithArgument = parseByName
[ ("ldrs", LDRS)
, ("strs", STRS) , ("strs", STRS)
, ("ldrf", LDRF) , ("ldrf", LDRF)
, ("strf", STRF) , ("strf", STRF)
] ]
lRawInstruction :: Parser (RawInstruction Address) lRawInstruction :: Parser (RawInstruction Address)
lRawInstruction = label "instruction" $ lRawInstruction = label "instruction" $ smallInstruction <|> largeInstruction
(RawSmallInstruction <$> smallOpcode <*> addr)
<|> (RawLargeInstruction <$> largeOpcode <*> optionalSv)
<|> (RawLargeInstruction <$> largeOpcodeWithArgument <*> sv)
where where
addr = lexeme space *> lexeme address smallInstruction = do
sv = lexeme space *> lexeme smallValue so <- smallOpcode
optionalSv = lexeme (lexeme space *> smallValue <|> pure 0) void $ lSpace
lv <- lexeme address
pure $ RawSmallInstruction so lv
largeInstruction = do
lo <- largeOpcode
if argumentIsOptional lo
then do
sv <- lexeme (try (lSpace *> smallValue) <|> pure 0)
pure $ RawLargeInstruction lo sv
else do
sv <- lSpace *> lexeme smallValue
pure $ RawLargeInstruction lo sv
cookInstruction :: RawInstruction MimaAddress -> Instruction cookInstruction :: RawInstruction MimaAddress -> Instruction
cookInstruction (RawSmallInstruction so lv) = SmallInstruction so lv cookInstruction (RawSmallInstruction so lv) = SmallInstruction so lv