replaced expression parse in asm with table-driven: it is slower, but smaller by...
[bz80asm.git] / main.zas
blobbad429306b60c8a178ec5425670fa0ad02034772
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  "ld   bc,2+3*5",13
238   defm  "push ix",13
239   defm  "pop  iy",13
240   defm  "ex   (sp),hl",13
241   defm  "push bc",13
242   defm  "push af,ix,de,hl",13
243   defm  "pop  af,iy,de,hl,bc",13
244   defm  "ld   bc,de",13
245   defm  "ld   bc,hl",13
246   defm  "ld   de,bc",13
247   defm  "ld   de,hl",13
248   defm  "ld   hl,bc",13
249   defm  "ld   hl,de",13
250   defm  "or   c:inc a ; comment",13
251   defm  "and  (hl)",13
252   defm  "exx",13
253   defm  "label cp  69",13
254   defm  "call 0BEEFh",13
255   defm  "jr   $",13
256   defm  "jr   label",13
257   defm  "djnz label3",13
258   defm  "ld   a,40+2",13
259   defm  "ld   b,44-2",13
260   defm  "ld   c,126/3",13
261   defm  "ld   e,427%10",13
262   defm  "ld   bc,2+3*5",13
263   defm  "ld   bc,0+(2+3)*5",13
264   defm  "ld   bc,[2+3]*5",13
265   defm  "ld   bc,(2+3)*5",13
266   defm  "label3 ld   hl,16384",13
267   defm  "ld   hl,#4001",13
268   defm  "ld   a,(ix-2)",13
269   defm  "ld   c,(ix)",13
270   defm  "ld   de,$1234",13
271   defm  "ld   bc,0x5b02",13
272   defm  "ld   a,0b1001",13
273   defm  "ld   a,%1010",13
274   defm  "ld   ix,-1234",13
275   defm  "ld   iy,-0x602a",13
276   defm  "cp   1<<3",13
277   defm  "cp   8>>2",13
278   defm  "cp   ~0-1",13
279   defm  "defb 7&$c,1|2,1|(3^1),1<<15",13
280   defm  "defw 1<<15",13
281   defm  "defm '012','34'",13
282   defb  0
284 dest: defs 64,0
287 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
289 ;; show listing
290 ;; extracted from assembler code, because we don't need it there
292 ;; IN:
293 ;;   IY: current position in text buffer
294 ;;   IX: current position in code buffer
295 ;;   BC: starting position in text buffer
296 ;;   HL: starting position in code buffer
297 ;;   DE: code length
298 ;; OUT:
299 ;;   IX, IY: unchanged
300 ;;   others are dead
302 ;COUNT:  defb  0  ;PRINT POSITION
303 ASM_LISTING:
304   ld    a,d
305   or    e
306   ret   z   ; no code -- nothing to do
308   push  ix
310   ld    (.codelen),de
311   ld    (.codestart),hl
313   ; calculate original PC
314   ld    hl,(BZ80ASM.PC)
315   or    a
316   sbc   hl,de
317   ; print original PC
318   push  hl
319   ld    a,h
320   call  HEX
321   pop   hl
322   ld    a,l
323   call  HEXSP
325   ; print code bytes (if there are any)
326   ld    de,(.codelen)
327   ld    a,d
328   or    a
329   jr    nz,.nocode
330   ; do not print code if more than 4 bytes (long strings and dbs)
331   or    e
332   jr    z,.nocode
333   ; do not print code if more than 4 bytes (long strings and dbs)
334   cp    5
335   jr    nc,.nocode
337   ; print hex bytes
338   ld    hl,(.codestart)
339 .cdumploop:
340   ld    a,(hl)
341   call  HEXSP
342   inc   hl
343   dec   e
344   jr    nz,.cdumploop
345   ; align printed code
346   ld    a,(.codelen)
347 .alignloop:
348   cp    a,4
349   jr    nc,.aligndone
350   ld    e,a
351   ld    a,32
352   call  EMIT
353   ld    a,32
354   call  EMIT
355   ld    a,32
356   call  EMIT
357   ld    a,e
358   inc   a
359   jr    .alignloop
360 .aligndone:
362 .nocode:
363   ; print source line, from BC to IY (exclusive)
364   ; calculate string length
365   push  iy
366   pop   hl
367   or    a
368   sbc   hl,bc
369   jr    z,.notextline
370 .textloop:
371   ld    a,(bc)
372   call  EMIT
373   inc   bc
374   dec   hl
375   ld    a,h
376   or    l
377   jr    nz,.textloop
378 .notextline:
379   ; print final CR
380   ld    a,13
381   call  EMIT
383   pop   ix
384   ret
386 .codelen: defw 0
387 .codestart: defw 0
390 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
392 ;; print byte in hex with the trailing space
394 HEXSP:
395   call  HEX
396   ld    a,' '
397   jr    OUTCH1
400 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
402 ;; print byte in hex
404 HEX:
405   push  af
406   rrca
407   rrca
408   rrca
409   rrca
410   call  HEXOUT
411   pop   af
412 HEXOUT:
413   and   0FH
414   add   a,90H
415   daa
416   adc   a,40H
417   daa
418 OUTCH1:
419   jp    EMIT
422 LABMAN_FIRST_LABEL: defw $+2