implemented "division by zero" check in asm; still, it is 7 bytes smaller! ;-)
[bz80asm.git] / main.zas
blob9a814086fff5d117e5a3274cbc9181e2151013e1
1   $refopt alllabels
3   org   #8000
4   ent   main
6   include "bzasm80.zas"
8 csizestart = $
9   include "labman.zas"
10 csizeend = $
11 $printf "label manager size: %d", csizeend-csizestart
13 csizestart = $
14   include "output.zas"
15 csizeend = $
16 $printf "ouput system size: %d", csizeend-csizestart
18 csizestart = $
19   ;include "output_driver_std.zas"
20   include "output_driver_4x8.zas"
21 csizeend = $
22 $printf "printing driver size: %d", csizeend-csizestart
24 ; so they won't clutter symbol table
25 csizeend = -1
26 csizestart = -1
28   include "disz80.zas"
30 asmdest equ #C000
32 main:
33   call  emitInit
35   ; setup callbacks
36   ld    hl,expr_error_cb
37   ld    (BZ80ASM.EXPR_ERROR_CB),hl
39   ld    hl,expr_error_jrfar_cb
40   ld    (BZ80ASM.ASM_JR_TOO_FAR_CB),hl
42   ld    hl,LABMAN_FIND_LABEL
43   ld    (BZ80ASM.GETLABEL_CB),hl
45   call  LABMAN_INIT
47   di
49   ; two-pass assemling
50 asm_another_pass:
51   ld    hl,msg_pass_header
52   call  printstr
53   ld    a,(LABMAN_PASS)
54   add   '0'+1
55   call  EMIT
56   ld    hl,msg_pass_footer
57   call  printstrnl
59   ld    ix,asmdest
60   ld    (BZ80ASM.PC),ix
61   ld    iy,strbuf
63 asmmore:
64   ; print line to assemble
65   $IF 0
66   push  iy
67 .dumploop:
68   ld    a,(iy)
69   or    a
70   jr    z,.dumpdone
71   cp    13
72   jr    z,.dumpdone
73   call  EMIT
74   inc   iy
75   jr    .dumploop
76 .dumpdone:
77   pop   iy
78   ld    a,13
79   call  EMIT
80   $ENDIF
82 doasm:
83   push  ix      ; save code destination
84   push  iy      ; we'll need it for listing
85 doasm_nopush:
86   call  BZ80ASM.ASSEM
87   jp    c,list_and_error
88 doasm_done_line:
89   ; DE is code length here
90   pop   bc      ; text starting position
91   pop   hl      ; code starting position
92   call  ASM_LISTING
94   ; check for line terminator
95   ; actually, anything except ':' is line terminator here
96   ; 0 terminates the whole buffer
97   ld    a,(iy)
98   inc   iy
99   or    a
100   jr    z,.bufferdone
101   cp    ':'
102   jr    z,asmmore
103   dec   iy
104 .skip_line:
105   ; skip current line
106   ld    a,(iy)
107   inc   iy
108   or    a
109   jr    z,.bufferdone
110   cp    13
111   jr    nz,.skip_line
112   ; check for buffer termination again
113   ; this pasta sux
114   ld    a,(iy)
115   or    a
116   jr    nz,asmmore
117 .bufferdone:
119   ; advance pass
120   call  LABMAN_ADVANCE_PASS
121   cp    2
122   jr    c,asm_another_pass
124   ; now disasm it
125   ld    hl,msg_disasm
126   call  printstrnl
128   ld    hl,OSWRCH
129   ld    (DISZ80.EMIT_CB),hl
131   push  ix
132   pop   de
133   ld    hl,asmdest
134 disloop:
135   ; HL: address to disasm
136   ; DE: end address
137   push  de
138   ex    de,hl
139   call  DISZ80.DISASM
140   ex    de,hl
141   ld    a,13
142   call  OSWRCH
143   pop   de
144   push  hl
145   or    a
146   sbc   hl,de
147   pop   hl
148   jr    c,disloop
149   ; done with disasm
151   ld    a,6
152   out   (#fe),a
153   jr    $
155 msg_disasm: defm 13,13,"--------",13,"DISASSEMBLY",13,"--------",13+#80
157 trylabel:
158   ld    hl,(BZ80ASM.PC)
159   call  LABMAN_DEFINE_LABEL
160   jr    c,bad_label_name_error
161   call  BZ80ASM.SKIP
162   ; if terminator, don't try to assemble more
163   jr    z,.linedone
164   jp    doasm_nopush
165 .linedone:
166   jp    doasm_done_line
167 .lineerr:
168   jr    list_and_error_no_label_check
171 bad_label_name_error:
172   ld    a,BZ80ASM.EXPR_ERR_INVALID_LABEL_NAME
173   jp    BZ80ASM.PARSE_EXPR_ERROR_A
175 list_and_error:
176   ; bad mnemonics?
177   ld    a,(BZ80ASM.ASM_BAD_B)
178   cp    255
179   jr    z,trylabel
181 list_and_error_no_label_check:
182   ld    hl,errline
183   call  printstrnl
184   push  iy
185   pop   hl    ; current position in text buffer
186   pop   de    ; initial position
187   ; calc length
188   or    a
189   sbc   hl,de
190   jr    z,.nothing
191   ; de: print from here
192   ; hl: length
193 .prloop:
194   ld    a,(de)
195   call  EMIT
196   inc   de
197   dec   hl
198   ld    a,h
199   or    l
200   jr    nz,.prloop
201   dec   de
202   ld    a,(de)
203   or    a
204   jr    z,.doneerrlist
205   cp    13
206   jr    z,.doneerrlist
207   inc   de
208   ld    a,'|'
209   call  EMIT
210 .nothing:
211   ld    a,(de)
212   call  EMIT
213   ld    a,(de)
214   inc   de
215   cp    13
216   jr    nz,.nothing
218 .doneerrlist:
219   ld    hl,errline
220   call  printstrnl
221   ;jp    error_syntax
222   di
223   ld    a,2
224   out   (#fe),a
225   jr    $
226 errline: defx "---------"
229 msg_pass_header:
230   defm "***************",13
231   defx "*** PASS #"
232 msg_pass_footer:
233   defm " ***",13
234   defx "***************"
236 strbuf:
237   defm  "push ix",13
238   defm  "pop  iy",13
239   defm  "ex   (sp),hl",13
240   defm  "push bc",13
241   defm  "push af,ix,de,hl",13
242   defm  "pop  af,iy,de,hl,bc",13
243   defm  "ld   bc,de",13
244   defm  "ld   bc,hl",13
245   defm  "ld   de,bc",13
246   defm  "ld   de,hl",13
247   defm  "ld   hl,bc",13
248   defm  "ld   hl,de",13
249   defm  "or   c:inc a ; comment",13
250   defm  "and  (hl)",13
251   defm  "exx",13
252   defm  "label cp  69",13
253   defm  "call 0BEEFh",13
254   defm  "jr   $",13
255   defm  "jr   label",13
256   defm  "djnz label3",13
257   defm  "ld   a,40+2",13
258   defm  "ld   b,44-2",13
259   defm  "ld   c,126/3",13
260   defm  "ld   e,427%10",13
261   defm  "ld   bc,2+3*5",13
262   defm  "ld   bc,0+(2+3)*5",13
263   defm  "ld   bc,[2+3]*5",13
264   defm  "ld   bc,(2+3)*5",13
265   defm  "label3 ld   hl,16384",13
266   defm  "ld   hl,#4001",13
267   defm  "ld   a,(ix-2)",13
268   defm  "ld   c,(ix)",13
269   defm  "ld   de,$1234",13
270   defm  "ld   bc,0x5b02",13
271   defm  "ld   a,0b1001",13
272   defm  "ld   a,%1010",13
273   defm  "ld   ix,-1234",13
274   defm  "ld   iy,-0x602a",13
275   defm  "cp   1<<3",13
276   defm  "cp   8>>2",13
277   defm  "cp   ~0-1",13
278   defm  "defb 7&$c,1|2,1|(3^1),1<<15",13
279   defm  "defw 1<<15",13
280   defm  "defm '012','34'",13
281   defb  0
283 dest: defs 64,0
286 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
288 ;; show listing
289 ;; extracted from assembler code, because we don't need it there
291 ;; IN:
292 ;;   IY: current position in text buffer
293 ;;   IX: current position in code buffer
294 ;;   BC: starting position in text buffer
295 ;;   HL: starting position in code buffer
296 ;;   DE: code length
297 ;; OUT:
298 ;;   IX, IY: unchanged
299 ;;   others are dead
301 ;COUNT:  defb  0  ;PRINT POSITION
302 ASM_LISTING:
303   ld    a,d
304   or    e
305   ret   z   ; no code -- nothing to do
307   push  ix
309   ld    (.codelen),de
310   ld    (.codestart),hl
312   ; calculate original PC
313   ld    hl,(BZ80ASM.PC)
314   or    a
315   sbc   hl,de
316   ; print original PC
317   push  hl
318   ld    a,h
319   call  HEX
320   pop   hl
321   ld    a,l
322   call  HEXSP
324   ; print code bytes (if there are any)
325   ld    de,(.codelen)
326   ld    a,d
327   or    a
328   jr    nz,.nocode
329   ; do not print code if more than 4 bytes (long strings and dbs)
330   or    e
331   jr    z,.nocode
332   ; do not print code if more than 4 bytes (long strings and dbs)
333   cp    5
334   jr    nc,.nocode
336   ; print hex bytes
337   ld    hl,(.codestart)
338 .cdumploop:
339   ld    a,(hl)
340   call  HEXSP
341   inc   hl
342   dec   e
343   jr    nz,.cdumploop
344   ; align printed code
345   ld    a,(.codelen)
346 .alignloop:
347   cp    a,4
348   jr    nc,.aligndone
349   ld    e,a
350   ld    a,32
351   call  EMIT
352   ld    a,32
353   call  EMIT
354   ld    a,32
355   call  EMIT
356   ld    a,e
357   inc   a
358   jr    .alignloop
359 .aligndone:
361 .nocode:
362   ; print source line, from BC to IY (exclusive)
363   ; calculate string length
364   push  iy
365   pop   hl
366   or    a
367   sbc   hl,bc
368   jr    z,.notextline
369 .textloop:
370   ld    a,(bc)
371   call  EMIT
372   inc   bc
373   dec   hl
374   ld    a,h
375   or    l
376   jr    nz,.textloop
377 .notextline:
378   ; print final CR
379   ld    a,13
380   call  EMIT
382   pop   ix
383   ret
385 .codelen: defw 0
386 .codestart: defw 0
389 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
391 ;; print byte in hex with the trailing space
393 HEXSP:
394   call  HEX
395   ld    a,' '
396   jr    OUTCH1
399 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
401 ;; print byte in hex
403 HEX:
404   push  af
405   rrca
406   rrca
407   rrca
408   rrca
409   call  HEXOUT
410   pop   af
411 HEXOUT:
412   and   0FH
413   add   a,90H
414   daa
415   adc   a,40H
416   daa
417 OUTCH1:
418   jp    EMIT
421 LABMAN_FIRST_LABEL: defw $+2