@@ -13,6 +13,7 @@ module Z80.Assembler
1313 , code
1414 , Bytes (.. )
1515 , db
16+ , resb
1617 , equ
1718 , label
1819 , labelled
@@ -39,6 +40,7 @@ import Z80.Operands
3940data ASMState
4041 = ASMState
4142 { loc :: Location
43+ , lastLoc :: Location
4244 , entry :: Maybe Location
4345 }
4446
@@ -53,34 +55,49 @@ data ASMBlock
5355 , asmData :: ByteString
5456 } deriving (Eq , Show )
5557
56- incrementLoc :: Location -> ASMState -> ASMState
57- incrementLoc x st = st { loc = loc st + x }
58+ fillToLoc :: Z80ASM
59+ fillToLoc = Z80 $ do
60+ padding <- gets $ \ st -> loc st - lastLoc st
61+ tell $ BS. replicate (fromIntegral padding) 0x00
62+
63+ incrementLoc :: Location -> Z80ASM
64+ incrementLoc x = do
65+ fillToLoc
66+ Z80 $ modify $ \ st -> let loc' = loc st + x in st{ loc = loc', lastLoc = loc' }
67+
68+ reserveLoc :: Location -> ASMState -> ASMState
69+ reserveLoc x st = st{ loc = loc st + x }
70+
71+ tellBytes :: [Word8 ] -> Z80ASM
72+ tellBytes bytes = do
73+ Z80 $ tell $ BS. pack bytes
74+ incrementLoc . fromIntegral $ length bytes
75+ -- The new location has to be computed lazily in the actual
76+ -- content of the bytes, so that we can emit byte values
77+ -- referring to later labels.
5878
5979code :: [Word8 ] -> Z80ASM
60- code bytes = Z80 $ do
61- tell $ BS. pack bytes
62- modify (incrementLoc . fromIntegral $ length bytes)
80+ code = tellBytes
6381
6482class Bytes a where
6583 defb :: a -> Z80ASM
6684
6785instance Bytes ByteString where
6886 defb = defByteString
6987instance (b ~ Word8 ) => Bytes [b ] where
70- defb bs = Z80 $ do
71- tell $ BS. pack bs
72- modify (incrementLoc . fromIntegral $ length bs)
73- -- The new location has to be computed lazily in the actual
74- -- content of the bytes, so that we can emit byte values
75- -- referring to later labels.
88+ defb = tellBytes
7689
7790db :: Bytes a => a -> Z80ASM
7891db = defb
7992
93+ resb :: Word16 -> Z80ASM
94+ resb n = Z80 $ do
95+ modify $ reserveLoc n
96+
8097defByteString :: ByteString -> Z80ASM
81- defByteString bs = Z80 $ do
82- tell bs
83- modify ( incrementLoc . fromIntegral $ BS. length bs)
98+ defByteString bs = do
99+ Z80 $ tell bs
100+ incrementLoc . fromIntegral $ BS. length bs
84101
85102label :: Z80 Location
86103label = loc <$> Z80 get
@@ -102,16 +119,18 @@ beginExecution :: Z80ASM
102119beginExecution = do
103120 l <- label
104121 Z80 . modify $ setEntry l
105- where setEntry l st@ (ASMState _ Nothing ) = st { entry = Just l }
106- setEntry l st@ (ASMState _ (Just e)) =
107- error $ " Cannot set execution start point twice. First start point: " ++ show e ++
108- " This start point: " ++ show l
122+ where setEntry l st = case entry st of
123+ Nothing -> st{ entry = Just l }
124+ Just e ->
125+ error $ " Cannot set execution start point twice. First start point: " ++ show e ++
126+ " This start point: " ++ show l
109127
110128org :: Location -> Z80ASM -> ASMBlock
111129org addr (Z80 mc) = ASMBlock { asmOrg = addr,
112130 asmEntry = fromMaybe addr $ entry finalState,
113- asmData = asm }
114- where (() , finalState, asm) = runRWS mc () (ASMState addr Nothing )
131+ asmData = truncate asm }
132+ where (() , finalState, asm) = runRWS mc () (ASMState addr addr Nothing )
133+ truncate = BS. take (fromIntegral $ lastLoc finalState - addr)
115134
116135equ :: a -> Z80 a
117136equ = return
0 commit comments