Skip to content

Commit 04e904f

Browse files
committed
Add resb to reserve uninitialized bytes. Only really makes sense at the end
1 parent 9ff6d5e commit 04e904f

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

src/Z80/Assembler.hs

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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
3940
data 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

5979
code :: [Word8] -> Z80ASM
60-
code bytes = Z80 $ do
61-
tell $ BS.pack bytes
62-
modify (incrementLoc . fromIntegral $ length bytes)
80+
code = tellBytes
6381

6482
class Bytes a where
6583
defb :: a -> Z80ASM
6684

6785
instance Bytes ByteString where
6886
defb = defByteString
6987
instance (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

7790
db :: Bytes a => a -> Z80ASM
7891
db = defb
7992

93+
resb :: Word16 -> Z80ASM
94+
resb n = Z80 $ do
95+
modify $ reserveLoc n
96+
8097
defByteString :: 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

85102
label :: Z80 Location
86103
label = loc <$> Z80 get
@@ -102,16 +119,18 @@ beginExecution :: Z80ASM
102119
beginExecution = 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

110128
org :: Location -> Z80ASM -> ASMBlock
111129
org 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

116135
equ :: a -> Z80 a
117136
equ = return

0 commit comments

Comments
 (0)