1 /* syntax.c syntax module for vasm */
2 /* (c) in 2002-2018 by Frank Wille */
3
4 #include "vasm.h"
5
6 /* The syntax module parses the input (read_next_line), handles
7 assembly-directives (section, data-storage etc.) and parses
8 mnemonics. Assembly instructions are split up in mnemonic name,
9 qualifiers and operands. new_inst returns a matching instruction,
10 if one exists.
11 Routines for creating sections and adding atoms to sections will
12 be provided by the main module.
13 */
14
15 char *syntax_copyright="vasm oldstyle syntax module 0.13e (c) 2002-2018 Frank Wille";
16 hashtable *dirhash;
17
18 static char textname[]=".text",textattr[]="acrx";
19 static char dataname[]=".data",dataattr[]="adrw";
20 static char rodataname[]=".rodata",rodataattr[]="adr";
21 static char bssname[]=".bss",bssattr[]="aurw";
22
23 char commentchar=';';
24 char *defsectname = textname;
25 char *defsecttype = "acrwx";
26
27 static char macname[] = ".mac";
28 static char macroname[] = ".macro";
29 static char eqname[] = ".eq";
30 static char equname[] = ".equ";
31 static char setname[] = ".set";
32
33 static char endmname[] = ".endmacro";
34 static char endrname[] = ".endrepeat";
35 static char reptname[] = ".rept";
36 static char repeatname[] = ".repeat";
37 static struct namelen endm_dirlist[] = {
38 { 4,&endmname[1] }, { 6,&endmname[1] }, { 8,&endmname[1] }, { 0,0 }
39 };
40 static struct namelen rept_dirlist[] = {
41 { 4,&reptname[1] }, { 6,&repeatname[1] }, { 0,0 }
42 };
43 static struct namelen endr_dirlist[] = {
44 { 4,&endrname[1] }, { 6,&endrname[1] }, { 9,&endrname[1] }, { 0,0 }
45 };
46 static struct namelen dendm_dirlist[] = {
47 { 5,&endmname[0] }, { 7,&endmname[0] }, { 9,&endmname[0] }, { 0,0 }
48 };
49 static struct namelen drept_dirlist[] = {
50 { 5,&reptname[0] }, { 7,&repeatname[0] }, { 0,0 }
51 };
52 static struct namelen dendr_dirlist[] = {
53 { 5,&endrname[0] }, { 7,&endrname[0] }, { 10,&endrname[0] }, { 0,0 }
54 };
55
56 static int dotdirs,autoexport,parse_end,igntrail,nocprefix,nointelsuffix;
57 static taddr orgmode = ~0;
58
59
skip(char * s)60 char *skip(char *s)
61 {
62 while (isspace((unsigned char )*s))
63 s++;
64 return s;
65 }
66
67
68 /* check for end of line, issue error, if not */
eol(char * s)69 void eol(char *s)
70 {
71 if (igntrail) {
72 if (!ISEOL(s) && !isspace((unsigned char)*s))
73 syntax_error(6);
74 }
75 else {
76 s = skip(s);
77 if (!ISEOL(s))
78 syntax_error(6);
79 }
80 }
81
82
exp_skip(char * s)83 char *exp_skip(char *s)
84 {
85 if (!igntrail) {
86 s = skip(s);
87 if (*s == commentchar)
88 *s = '\0'; /* rest of operand is ignored */
89 }
90 else if (isspace((unsigned char)*s) || *s==commentchar)
91 *s = '\0'; /* rest of operand is ignored */
92 return s;
93 }
94
95
skip_oper(int instoper,char * s)96 static char *skip_oper(int instoper,char *s)
97 {
98 #ifdef VASM_CPU_Z80
99 unsigned char lastuc = 0;
100 #endif
101 int par_cnt = 0;
102 char c = 0;
103
104 for (;;) {
105 s = exp_skip(s);
106 #ifdef VASM_CPU_Z80
107 if (c)
108 lastuc = toupper((unsigned char)*(s-1));
109 #endif
110 c = *s;
111
112 if (START_PARENTH(c))
113 par_cnt++;
114 else if (END_PARENTH(c)) {
115 if (par_cnt>0)
116 par_cnt--;
117 else
118 syntax_error(3); /* too many closing parentheses */
119 }
120 #ifdef VASM_CPU_Z80
121 /* For the Z80 ignore ' behind a letter, as it may be a register */
122 else if ((c=='\'' && (lastuc<'A' || lastuc>'Z')) || c=='\"')
123 #else
124 else if (c=='\'' || c=='\"')
125 #endif
126 s = skip_string(s,c,NULL) - 1;
127 else if (instoper && OPERSEP_COMMA && c==',' && par_cnt==0)
128 break;
129 else if (instoper && OPERSEP_BLANK && isspace((unsigned char)c)
130 && par_cnt==0)
131 break;
132 else if (!instoper && c==',' && par_cnt==0)
133 break;
134 else if (c == '\0')
135 break;
136
137 s++;
138 }
139 if(par_cnt != 0)
140 syntax_error(4); /* missing closing parentheses */
141 return s;
142 }
143
144
skip_operand(char * s)145 char *skip_operand(char *s)
146 {
147 return skip_oper(1,s);
148 }
149
150
my_skip_macro_arg(char * s)151 char *my_skip_macro_arg(char *s)
152 {
153 if (*s == '\\')
154 s++; /* leading \ in argument list is optional */
155 return skip_identifier(s);
156 }
157
158
159 #define handle_data(a,b) handle_data_offset(a,b,0)
160
handle_data_offset(char * s,int size,int offset)161 static void handle_data_offset(char *s,int size,int offset)
162 {
163 for (;;) {
164 char *opstart = s;
165 operand *op;
166 dblock *db = NULL;
167
168 if (size==8 && (*s=='\"' || *s=='\'')) {
169 if (db = parse_string(&opstart,*s,8)) {
170 #if defined(VASM_CPU_650X) || defined(VASM_CPU_Z80) || defined(VASM_CPU_6800)
171 if (offset != 0) {
172 int i;
173
174 for (i=0; i<db->size; i++)
175 db->data[i] = db->data[i] + offset;
176 }
177 #endif
178 add_atom(0,new_data_atom(db,1));
179 s = opstart;
180 }
181 }
182 if (!db) {
183 op = new_operand();
184 s = skip_oper(0,s);
185 if (parse_operand(opstart,s-opstart,op,DATA_OPERAND(size))) {
186 atom *a;
187
188 #if defined(VASM_CPU_650X) || defined(VASM_CPU_Z80) || defined(VASM_CPU_6800)
189 if (offset != 0)
190 op->value = make_expr(ADD,number_expr(offset),op->value);
191 #endif
192 a = new_datadef_atom(abs(size),op);
193 a->align = 1;
194 add_atom(0,a);
195 }
196 else
197 syntax_error(8); /* invalid data operand */
198 }
199
200 s = skip(s);
201 if (*s == ',') {
202 s = skip(s+1);
203 }
204 else if (*s == commentchar) {
205 break;
206 }
207 else if (*s) {
208 syntax_error(9); /* , expected */
209 return;
210 }
211 else
212 break;
213 }
214
215 eol(s);
216 }
217
218
handle_text(char * s)219 static void handle_text(char *s)
220 {
221 char *opstart = s;
222 operand *op;
223 dblock *db = NULL;
224
225 if (db = parse_string(&opstart,*s,8)) {
226 add_atom(0,new_data_atom(db,1));
227 s = opstart;
228 }
229 if (!db) {
230 op = new_operand();
231 s = skip_oper(0,s);
232 if (parse_operand(opstart,s-opstart,op,DATA_OPERAND(8))) {
233 atom *a;
234
235 a = new_datadef_atom(8,op);
236 a->align = 1;
237 add_atom(0,a);
238 }
239 else
240 syntax_error(8); /* invalid data operand */
241 }
242 eol(s);
243 }
244
245
handle_d8(char * s)246 static void handle_d8(char *s)
247 {
248 handle_data(s,8);
249 }
250
251
handle_d16(char * s)252 static void handle_d16(char *s)
253 {
254 handle_data(s,16);
255 }
256
257
handle_d24(char * s)258 static void handle_d24(char *s)
259 {
260 handle_data(s,24);
261 }
262
263
handle_d32(char * s)264 static void handle_d32(char *s)
265 {
266 handle_data(s,32);
267 }
268
269
270 #if defined(VASM_CPU_650X) || defined(VASM_CPU_Z80) || defined(VASM_CPU_6800)
handle_d8_offset(char * s)271 static void handle_d8_offset(char *s)
272 {
273 taddr offs = parse_constexpr(&s);
274
275 s = skip(s);
276 if (*s == ',') {
277 s = skip(s+1);
278 handle_data_offset(s,8,offs);
279 }
280 else
281 syntax_error(9); /* , expected */
282 }
283 #endif
284
285
do_alignment(taddr align,expr * offset)286 static void do_alignment(taddr align,expr *offset)
287 {
288 atom *a = new_space_atom(offset,1,0);
289
290 a->align = align;
291 add_atom(0,a);
292 }
293
294
handle_align(char * s)295 static void handle_align(char *s)
296 {
297 taddr a = parse_constexpr(&s);
298
299 if (a > 63)
300 syntax_error(21); /* bad alignment */
301 do_alignment(1LL<<a,number_expr(0));
302 eol(s);
303 }
304
305
handle_even(char * s)306 static void handle_even(char *s)
307 {
308 do_alignment(2,number_expr(0));
309 eol(s);
310 }
311
312
do_space(int size,expr * cnt,expr * fill)313 static void do_space(int size,expr *cnt,expr *fill)
314 {
315 add_atom(0,new_space_atom(cnt,size>>3,fill));
316 }
317
318
handle_space(char * s,int size)319 static void handle_space(char *s,int size)
320 {
321 expr *cnt,*fill=0;
322
323 cnt = parse_expr_tmplab(&s);
324 s = skip(s);
325 if (*s == ',') {
326 s = skip(s+1);
327 fill = parse_expr_tmplab(&s);
328 }
329 do_space(size,cnt,fill);
330 eol(s);
331 }
332
333
handle_fixedspc1(char * s)334 static void handle_fixedspc1(char *s)
335 {
336 do_space(8,number_expr(1),0);
337 eol(s);
338 }
339
340
handle_fixedspc2(char * s)341 static void handle_fixedspc2(char *s)
342 {
343 do_space(8,number_expr(2),0);
344 eol(s);
345 }
346
347
handle_spc8(char * s)348 static void handle_spc8(char *s)
349 {
350 handle_space(s,8);
351 }
352
353
handle_spc16(char * s)354 static void handle_spc16(char *s)
355 {
356 handle_space(s,16);
357 }
358
359
360 #if 0
361 static void handle_spc24(char *s)
362 {
363 handle_space(s,24);
364 }
365
366
367 static void handle_spc32(char *s)
368 {
369 handle_space(s,32);
370 }
371 #endif
372
373
handle_string(char * s)374 static void handle_string(char *s)
375 {
376 handle_data(s,8);
377 add_atom(0,new_space_atom(number_expr(1),1,0)); /* terminating zero */
378 }
379
380
handle_end(char * s)381 static void handle_end(char *s)
382 {
383 parse_end = 1;
384 eol(s);
385 }
386
387
handle_fail(char * s)388 static void handle_fail(char *s)
389 {
390 add_atom(0,new_assert_atom(NULL,NULL,mystrdup(s)));
391 }
392
393
handle_org(char * s)394 static void handle_org(char *s)
395 {
396 if (*s == current_pc_char) {
397 char *s2 = skip(s+1);
398
399 if (*s2++ == '+') {
400 handle_space(skip(s2),8); /* "* = * + <expr>" to reserves bytes */
401 return;
402 }
403 }
404 set_section(new_org(parse_constexpr(&s)));
405 eol(s);
406 }
407
408
handle_rorg(char * s)409 static void handle_rorg(char *s)
410 {
411 start_rorg(parse_constexpr(&s));
412 eol(s);
413 }
414
415
handle_rend(char * s)416 static void handle_rend(char *s)
417 {
418 if (end_rorg())
419 eol(s);
420 }
421
422
handle_roffs(char * s)423 static void handle_roffs(char *s)
424 {
425 add_atom(0,new_roffs_atom(parse_expr_tmplab(&s)));
426 }
427
428
handle_section(char * s)429 static void handle_section(char *s)
430 {
431 char *name,*attr;
432
433 if (!(name=parse_name(&s)))
434 return;
435 if (*s==',') {
436 s = skip(s+1);
437 attr = s;
438 if (*s!= '\"')
439 syntax_error(7,'\"'); /* " expected */
440 else
441 s++;
442 attr = s;
443 while (*s&&*s!='\"')
444 s++;
445 attr = cnvstr(attr,s-attr);
446 s = skip(s+1);
447 }
448 else {
449 if (!strcmp(name,textname)) attr = textattr;
450 if (!strcmp(name,dataname)) attr = dataattr;
451 if (!strcmp(name,rodataname)) attr = rodataattr;
452 if (!strcmp(name,bssname)) attr = bssattr;
453 else attr = defsecttype;
454 }
455
456 new_section(name,attr,1);
457 switch_section(name,attr);
458 eol(s);
459 }
460
461
do_binding(char * s,int bind)462 static void do_binding(char *s,int bind)
463 {
464 symbol *sym;
465 char *name;
466
467 while (1) {
468 if (!(name=parse_identifier(&s)))
469 return;
470 sym = new_import(name);
471 myfree(name);
472 if (sym->flags&(EXPORT|WEAK|LOCAL)!=0 &&
473 sym->flags&(EXPORT|WEAK|LOCAL)!=bind)
474 general_error(62,sym->name,get_bind_name(sym)); /* binding already set */
475 else
476 sym->flags |= bind;
477 s = skip(s);
478 if (*s != ',')
479 break;
480 s = skip(s+1);
481 }
482 eol(s);
483 }
484
485
handle_global(char * s)486 static void handle_global(char *s)
487 {
488 do_binding(s,EXPORT);
489 }
490
491
handle_weak(char * s)492 static void handle_weak(char *s)
493 {
494 do_binding(s,WEAK);
495 }
496
497
handle_local(char * s)498 static void handle_local(char *s)
499 {
500 do_binding(s,LOCAL);
501 }
502
503
ifdef(char * s,int b)504 static void ifdef(char *s,int b)
505 {
506 char *name;
507 symbol *sym;
508 int result;
509
510 if (!(name = parse_symbol(&s))) {
511 syntax_error(10); /* identifier expected */
512 return;
513 }
514 if (sym = find_symbol(name))
515 result = sym->type != IMPORT;
516 else
517 result = 0;
518 myfree(name);
519 cond_if(result == b);
520 eol(s);
521 }
522
523
ifused(char * s,int b)524 static void ifused(char *s, int b)
525 {
526 char *name;
527 symbol *sym;
528 int result;
529
530 if (!(name = parse_identifier(&s))) {
531 syntax_error(10); /* identifier expected */
532 return;
533 }
534
535 if (sym = find_symbol(name)) {
536 if (sym->type != IMPORT) {
537 syntax_error(22,name);
538 result = 0;
539 }
540 else
541 result = 1;
542 }
543 else
544 result = 0;
545
546 myfree(name);
547 cond_if(result == b);
548 eol(s);
549 }
550
551
handle_ifused(char * s)552 static void handle_ifused(char *s)
553 {
554 ifused(s,1);
555 }
556
557
handle_ifnused(char * s)558 static void handle_ifnused(char *s)
559 {
560 ifused(s,0);
561 }
562
563
handle_ifd(char * s)564 static void handle_ifd(char *s)
565 {
566 ifdef(s,1);
567 }
568
569
handle_ifnd(char * s)570 static void handle_ifnd(char *s)
571 {
572 ifdef(s,0);
573 }
574
575
ifexp(char * s,int c)576 static char *ifexp(char *s,int c)
577 {
578 expr *condexp = parse_expr_tmplab(&s);
579 taddr val;
580 int b;
581
582 if (eval_expr(condexp,&val,NULL,0)) {
583 switch (c) {
584 case 0: b = val == 0; break;
585 case 1: b = val != 0; break;
586 case 2: b = val > 0; break;
587 case 3: b = val >= 0; break;
588 case 4: b = val < 0; break;
589 case 5: b = val <= 0; break;
590 default: ierror(0); break;
591 }
592 }
593 else {
594 general_error(30); /* expression must be constant */
595 b = 0;
596 }
597 cond_if(b);
598 free_expr(condexp);
599 return s;
600 }
601
602
handle_ifeq(char * s)603 static void handle_ifeq(char *s)
604 {
605 eol(ifexp(s,0));
606 }
607
608
handle_ifne(char * s)609 static void handle_ifne(char *s)
610 {
611 eol(ifexp(s,1));
612 }
613
614
handle_ifgt(char * s)615 static void handle_ifgt(char *s)
616 {
617 eol(ifexp(s,2));
618 }
619
620
handle_ifge(char * s)621 static void handle_ifge(char *s)
622 {
623 eol(ifexp(s,3));
624 }
625
626
handle_iflt(char * s)627 static void handle_iflt(char *s)
628 {
629 eol(ifexp(s,4));
630 }
631
632
handle_ifle(char * s)633 static void handle_ifle(char *s)
634 {
635 eol(ifexp(s,5));
636 }
637
638
handle_else(char * s)639 static void handle_else(char *s)
640 {
641 eol(s);
642 cond_skipelse();
643 }
644
645
handle_endif(char * s)646 static void handle_endif(char *s)
647 {
648 eol(s);
649 cond_endif();
650 }
651
652
handle_assert(char * s)653 static void handle_assert(char *s)
654 {
655 char *expstr,*msgstr;
656 size_t explen;
657 expr *aexp;
658 atom *a;
659
660 expstr = skip(s);
661 aexp = parse_expr(&s);
662 explen = s - expstr;
663 s = skip(s);
664 if (*s == ',') {
665 s = skip(s+1);
666 msgstr = parse_name(&s);
667 }
668 else
669 msgstr = NULL;
670
671 a = new_assert_atom(aexp,cnvstr(expstr,explen),msgstr);
672 add_atom(0,a);
673 }
674
675
handle_incdir(char * s)676 static void handle_incdir(char *s)
677 {
678 char *name;
679
680 if (name = parse_name(&s))
681 new_include_path(name);
682 eol(s);
683 }
684
685
handle_include(char * s)686 static void handle_include(char *s)
687 {
688 char *name;
689
690 if (name = parse_name(&s)) {
691 eol(s);
692 include_source(name);
693 }
694 }
695
696
handle_incbin(char * s)697 static void handle_incbin(char *s)
698 {
699 char *name;
700 long delta = 0;
701 unsigned long nbbytes = 0;
702
703 if (name = parse_name(&s)) {
704 s = skip(s);
705 if (*s == ',') {
706 s = skip(s+1);
707 delta = parse_constexpr(&s);
708 if (delta < 0)
709 delta = 0;
710 s = skip(s);
711 if (*s == ',') {
712 s = skip(s+1);
713 nbbytes = parse_constexpr(&s);
714 }
715 }
716 eol(s);
717 include_binary_file(name,delta,nbbytes);
718 }
719 }
720
721
handle_rept(char * s)722 static void handle_rept(char *s)
723 {
724 utaddr cnt = parse_constexpr(&s);
725
726 eol(s);
727 new_repeat((int)cnt,NULL,NULL,
728 dotdirs?drept_dirlist:rept_dirlist,
729 dotdirs?dendr_dirlist:endr_dirlist);
730 }
731
732
handle_endr(char * s)733 static void handle_endr(char *s)
734 {
735 syntax_error(12,&endrname[1],&repeatname[1]); /* unexpected endr without rept */
736 }
737
738
handle_macro(char * s)739 static void handle_macro(char *s)
740 {
741 char *name;
742
743 if (name = parse_identifier(&s)) {
744 s = skip(s);
745 if (*s == ',') { /* named macro arguments are given? */
746 s++;
747 }
748 else {
749 eol(s);
750 s = NULL;
751 }
752 new_macro(name,dotdirs?dendm_dirlist:endm_dirlist,s);
753 myfree(name);
754 }
755 else
756 syntax_error(10); /* identifier expected */
757 }
758
759
handle_endm(char * s)760 static void handle_endm(char *s)
761 {
762 syntax_error(12,&endmname[1],¯oname[1]); /* unexpected endm without macro */
763 }
764
765
handle_defc(char * s)766 static void handle_defc(char *s)
767 {
768 char *name;
769
770 s = skip(s);
771 name = parse_identifier(&s);
772 if ( name != NULL ) {
773 s = skip(s);
774 if ( *s == '=' ) {
775 s = skip(s+1);
776 new_abs(name,parse_expr_tmplab(&s));
777 }
778 myfree(name);
779 }
780 else
781 syntax_error(10);
782 }
783
784
handle_list(char * s)785 static void handle_list(char *s)
786 {
787 set_listing(1);
788 }
789
handle_nolist(char * s)790 static void handle_nolist(char *s)
791 {
792 set_listing(0);
793 }
794
handle_listttl(char * s)795 static void handle_listttl(char *s)
796 {
797 /* set listing file title */
798 }
799
handle_listsubttl(char * s)800 static void handle_listsubttl(char *s)
801 {
802 /* set listing file sub-title */
803 }
804
handle_listpage(char * s)805 static void handle_listpage(char *s)
806 {
807 /* new listing page */
808 }
809
handle_listspace(char * s)810 static void handle_listspace(char *s)
811 {
812 /* insert listing space */
813 }
814
815
handle_struct(char * s)816 static void handle_struct(char *s)
817 {
818 char *name;
819
820 if (name = parse_identifier(&s)) {
821 s = skip(s);
822 eol(s);
823 if (new_structure(name))
824 current_section->flags |= LABELS_ARE_LOCAL;
825 myfree(name);
826 }
827 else
828 syntax_error(10); /* identifier expected */
829 }
830
831
handle_endstruct(char * s)832 static void handle_endstruct(char *s)
833 {
834 section *prevsec;
835 symbol *szlabel;
836
837 if (end_structure(&prevsec)) {
838 /* create the structure name as label defining the structure size */
839 current_section->flags &= ~LABELS_ARE_LOCAL;
840 szlabel = new_labsym(0,current_section->name);
841 add_atom(0,new_label_atom(szlabel));
842 /* end structure declaration by switching to previous section */
843 set_section(prevsec);
844 }
845 eol(s);
846 }
847
848
849 struct {
850 char *name;
851 void (*func)(char *);
852 } directives[] = {
853 "org",handle_org,
854 "rorg",handle_rorg,
855 "rend",handle_rend,
856 "phase",handle_rorg,
857 "dephase",handle_rend,
858 "roffs",handle_roffs,
859 "align",handle_align,
860 "even",handle_even,
861 "byte",handle_d8,
862 "db",handle_d8,
863 "dfb",handle_d8,
864 "defb",handle_d8,
865 "asc",handle_d8,
866 "data",handle_d8,
867 "defm",handle_text,
868 "text",handle_text,
869 "wor",handle_d16,
870 "word",handle_d16,
871 "addr",handle_d16,
872 "dw",handle_d16,
873 "dfw",handle_d16,
874 "defw",handle_d16,
875 "dd",handle_d32,
876 #if defined(VASM_CPU_650X) || defined(VASM_CPU_Z80) || defined(VASM_CPU_6800)
877 "abyte",handle_d8_offset,
878 #endif
879 "ds",handle_spc8,
880 "dsb",handle_spc8,
881 "fill",handle_spc8,
882 "reserve",handle_spc8,
883 "spc",handle_spc8,
884 "dsw",handle_spc16,
885 "blk",handle_spc8,
886 "blkw",handle_spc16,
887 "dc",handle_spc8,
888 "byt",handle_fixedspc1,
889 "wrd",handle_fixedspc2,
890 "assert",handle_assert,
891 #if defined(VASM_CPU_TR3200) /* Clash with IFxx instructions of TR3200 cpu */
892 "if_def",handle_ifd,
893 "if_ndef",handle_ifnd,
894 "if_eq",handle_ifeq,
895 "if_ne",handle_ifne,
896 "if_gt",handle_ifgt,
897 "if_ge",handle_ifge,
898 "if_lt",handle_iflt,
899 "if_le",handle_ifle,
900 "if_used",handle_ifused,
901 "if_nused",handle_ifnused,
902 #else
903 "ifdef",handle_ifd,
904 "ifndef",handle_ifnd,
905 "ifd",handle_ifd,
906 "ifnd",handle_ifnd,
907 "ifeq",handle_ifeq,
908 "ifne",handle_ifne,
909 "ifgt",handle_ifgt,
910 "ifge",handle_ifge,
911 "iflt",handle_iflt,
912 "ifle",handle_ifle,
913 "ifused",handle_ifused,
914 "ifnused",handle_ifnused,
915 #endif
916 "if",handle_ifne,
917 "else",handle_else,
918 "el",handle_else,
919 "endif",handle_endif,
920 #if !defined(VASM_CPU_Z80) && !defined(VASM_CPU_6800)
921 "ei",handle_endif, /* Clashes with z80 opcode */
922 #endif
923 "incbin",handle_incbin,
924 "mdat",handle_incbin,
925 "incdir",handle_incdir,
926 "include",handle_include,
927 "rept",handle_rept,
928 "repeat",handle_rept,
929 "endr",handle_endr,
930 "endrep",handle_endr,
931 "endrepeat",handle_endr,
932 "mac",handle_macro,
933 "macro",handle_macro,
934 "endm",handle_endm,
935 "endmac",handle_endm,
936 "endmacro",handle_endm,
937 "end",handle_end,
938 "fail",handle_fail,
939 "section",handle_section,
940 "binary",handle_incbin,
941 "defs",handle_spc8,
942 "defp",handle_d24,
943 "defl",handle_d32,
944 "defc",handle_defc,
945 "xdef",handle_global,
946 "xref",handle_global,
947 "lib",handle_global,
948 "xlib",handle_global,
949 "global",handle_global,
950 "extern",handle_global,
951 "local",handle_local,
952 "weak",handle_weak,
953 "ascii",handle_string,
954 "asciiz",handle_string,
955 "string",handle_string,
956 "list",handle_list,
957 "nolist",handle_nolist,
958 "struct",handle_struct,
959 "structure",handle_struct,
960 "endstruct",handle_endstruct,
961 "endstructure",handle_endstruct,
962 "rmb",handle_spc8,
963 "fcc",handle_text,
964 "fcb",handle_d8,
965 "fdb",handle_d16,
966 "bsz",handle_spc8,
967 "zmb",handle_spc8,
968 "nam",handle_listttl,
969 "subttl",handle_listsubttl,
970 "page",handle_listpage,
971 "space",handle_listspace
972 };
973
974 int dir_cnt = sizeof(directives) / sizeof(directives[0]);
975
976
977 /* checks for a valid directive, and return index when found, -1 otherwise */
check_directive(char ** line)978 static int check_directive(char **line)
979 {
980 char *s,*name;
981 hashdata data;
982
983 s = skip(*line);
984 if (!ISIDSTART(*s))
985 return -1;
986 name = s++;
987 while (ISIDCHAR(*s))
988 s++;
989 if (*name=='.' && dotdirs)
990 name++;
991 if (!find_namelen_nc(dirhash,name,s-name,&data))
992 return -1;
993 *line = s;
994 return data.idx;
995 }
996
997
998 /* Handles assembly directives; returns non-zero if the line
999 was a directive. */
handle_directive(char * line)1000 static int handle_directive(char *line)
1001 {
1002 int idx = check_directive(&line);
1003
1004 if (idx >= 0) {
1005 directives[idx].func(skip(line));
1006 return 1;
1007 }
1008 return 0;
1009 }
1010
1011
oplen(char * e,char * s)1012 static int oplen(char *e,char *s)
1013 {
1014 while(s!=e&&isspace((unsigned char)e[-1]))
1015 e--;
1016 return e-s;
1017 }
1018
1019
1020 /* When a structure with this name exists, insert its atoms and either
1021 initialize with new values or accept its default values. */
execute_struct(char * name,int name_len,char * s)1022 static int execute_struct(char *name,int name_len,char *s)
1023 {
1024 section *str;
1025 atom *p;
1026
1027 str = find_structure(name,name_len);
1028 if (str == NULL)
1029 return 0;
1030
1031 for (p=str->first; p; p=p->next) {
1032 atom *new;
1033 char *opp;
1034 int opl;
1035
1036 if (p->type==DATA || p->type==SPACE || p->type==DATADEF) {
1037 opp = s = skip(s);
1038 s = skip_oper(0,s);
1039 opl = oplen(s,opp);
1040
1041 if (opl > 0) {
1042 /* initialize this atom with a new expression */
1043
1044 if (p->type == DATADEF) {
1045 /* parse a new data operand of the declared bitsize */
1046 operand *op;
1047
1048 op = new_operand();
1049 if (parse_operand(opp,opl,op,
1050 DATA_OPERAND(p->content.defb->bitsize))) {
1051 new = new_datadef_atom(p->content.defb->bitsize,op);
1052 new->align = p->align;
1053 add_atom(0,new);
1054 }
1055 else
1056 syntax_error(8); /* invalid data operand */
1057 }
1058 else if (p->type == SPACE) {
1059 /* parse the fill expression for this space */
1060 new = clone_atom(p);
1061 new->content.sb = new_sblock(p->content.sb->space_exp,
1062 p->content.sb->size,
1063 parse_expr_tmplab(&opp));
1064 new->content.sb->space = p->content.sb->space;
1065 add_atom(0,new);
1066 }
1067 else {
1068 /* parse constant data - probably a string, or a single constant */
1069 dblock *db;
1070
1071 db = new_dblock();
1072 db->size = p->content.db->size;
1073 db->data = db->size ? mycalloc(db->size) : NULL;
1074 if (db->data) {
1075 if (*opp=='\"' || *opp=='\'') {
1076 dblock *strdb;
1077
1078 strdb = parse_string(&opp,*opp,8);
1079 if (strdb->size) {
1080 if (strdb->size > db->size)
1081 syntax_error(24,strdb->size-db->size); /* cut last chars */
1082 memcpy(db->data,strdb->data,
1083 strdb->size > db->size ? db->size : strdb->size);
1084 myfree(strdb->data);
1085 }
1086 myfree(strdb);
1087 }
1088 else {
1089 taddr val = parse_constexpr(&opp);
1090 void *p;
1091
1092 if (db->size > sizeof(taddr) && BIGENDIAN)
1093 p = db->data + db->size - sizeof(taddr);
1094 else
1095 p = db->data;
1096 setval(BIGENDIAN,p,sizeof(taddr),val);
1097 }
1098 }
1099 add_atom(0,new_data_atom(db,p->align));
1100 }
1101 }
1102 else {
1103 /* empty: use default values from original atom */
1104 add_atom(0,clone_atom(p));
1105 }
1106
1107 s = skip(s);
1108 if (*s == ',')
1109 s++;
1110 }
1111 else if (p->type == INSTRUCTION)
1112 syntax_error(23); /* skipping instruction in struct init */
1113
1114 /* other atoms are silently ignored */
1115 }
1116
1117 eol(s);
1118 return 1;
1119 }
1120
1121
parse_label_or_pc(char ** start)1122 static char *parse_label_or_pc(char **start)
1123 {
1124 char *s,*name;
1125
1126 name = parse_labeldef(start,0);
1127 s = skip(*start);
1128 if (name==NULL && *s==current_pc_char && !ISIDCHAR(*(s+1))) {
1129 name = cnvstr(s,1);
1130 s = skip(s+1);
1131 }
1132 if (name)
1133 *start = s;
1134 return name;
1135 }
1136
1137
1138 #ifdef STATEMENT_DELIMITER
read_next_statement(void)1139 static char *read_next_statement(void)
1140 {
1141 static char *s = NULL;
1142 char *line,c;
1143
1144 if (s == NULL) {
1145 char *lab;
1146
1147 s = line = read_next_line();
1148 if (s == NULL)
1149 return NULL; /* no more lines in source */
1150
1151 /* skip label field and possible statement delimiters therein */
1152 if (lab = parse_label_or_pc(&s))
1153 myfree(lab);
1154 }
1155 else {
1156 /* make the new statement start with a blank - there is no label field */
1157 *s = ' ';
1158 line = s++;
1159 }
1160
1161 /* find next statement delimiter in line buffer */
1162 for (;;) {
1163 #ifdef VASM_CPU_Z80
1164 unsigned char lastuc;
1165 #endif
1166
1167 c = *s;
1168 #ifdef VASM_CPU_Z80
1169 /* For the Z80 ignore ' behind a letter, as it may be a register */
1170 lastuc = toupper((unsigned char)*(s-1));
1171 if ((c=='\'' && (lastuc<'A' || lastuc>'Z')) || c=='\"') {
1172 #else
1173 if (c=='\'' || c=='\"') {
1174 #endif
1175 s = skip_string(s,c,NULL);
1176 }
1177 else if (c == STATEMENT_DELIMITER) {
1178 *s = '\0'; /* terminate the statement here temporarily */
1179 break;
1180 }
1181 else if (c=='\0' || c==commentchar) {
1182 s = NULL; /* ignore delimiters in rest of line */
1183 break;
1184 }
1185 else
1186 s++;
1187 }
1188 return line;
1189 }
1190 #endif
1191
1192
1193 void parse(void)
1194 {
1195 char *s,*line,*inst,*labname;
1196 char *ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1];
1197 char *op[MAX_OPERANDS];
1198 int ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1];
1199 int op_len[MAX_OPERANDS];
1200 int ext_cnt,op_cnt,inst_len;
1201 instruction *ip;
1202
1203 #ifdef STATEMENT_DELIMITER
1204 while (line = read_next_statement()) {
1205 #else
1206 while (line = read_next_line()) {
1207 #endif
1208 if (parse_end)
1209 continue;
1210
1211 if (!cond_state()) {
1212 /* skip source until ELSE or ENDIF */
1213 int idx;
1214
1215 s = line;
1216 if (labname = parse_label_or_pc(&s))
1217 myfree(labname);
1218 idx = check_directive(&s);
1219 if (idx >= 0) {
1220 if (!strncmp(directives[idx].name,"if",2))
1221 cond_skipif();
1222 else if (directives[idx].func == handle_else)
1223 cond_else();
1224 else if (directives[idx].func == handle_endif)
1225 cond_endif();
1226 }
1227 continue;
1228 }
1229
1230 s = line;
1231 if (labname = parse_label_or_pc(&s)) {
1232 /* we have found a global or local label, or current-pc character */
1233 symbol *label,*labsym;
1234 int equlen = 0;
1235
1236 if (!strnicmp(s,equname+!dotdirs,3+dotdirs) &&
1237 isspace((unsigned char)*(s+3+dotdirs)))
1238 equlen = 3+dotdirs;
1239 else if (!strnicmp(s,eqname+!dotdirs,2+dotdirs) &&
1240 isspace((unsigned char)*(s+2+dotdirs)))
1241 equlen = 2+dotdirs;
1242 else if (*s == '=')
1243 equlen = 1;
1244
1245 if (equlen) {
1246 /* found a kind of equate directive */
1247 if (*labname == current_pc_char) {
1248 handle_org(skip(s+equlen));
1249 continue;
1250 }
1251 else {
1252 s = skip(s+equlen);
1253 label = new_equate(labname,parse_expr_tmplab(&s));
1254 }
1255 }
1256 else if (!strnicmp(s,setname+!dotdirs,3+dotdirs) &&
1257 isspace((unsigned char)*(s+3+dotdirs))) {
1258 /* SET allows redefinitions */
1259 if (*labname == current_pc_char) {
1260 syntax_error(10); /* identifier expected */
1261 }
1262 else {
1263 s = skip(s+3+dotdirs);
1264 label = new_abs(labname,parse_expr_tmplab(&s));
1265 }
1266 }
1267 else if (!strnicmp(s,macname+!dotdirs,3+dotdirs) &&
1268 (isspace((unsigned char)*(s+3+dotdirs)) ||
1269 *(s+3+dotdirs)=='\0') ||
1270 !strnicmp(s,macroname+!dotdirs,5+dotdirs) &&
1271 (isspace((unsigned char)*(s+5+dotdirs)) ||
1272 *(s+5+dotdirs)=='\0')) {
1273 char *params = skip(s + (*(s+3+dotdirs)=='r'?5+dotdirs:3+dotdirs));
1274
1275 s = line;
1276 myfree(labname);
1277 if (!(labname = parse_identifier(&s)))
1278 ierror(0);
1279 new_macro(labname,dotdirs?dendm_dirlist:endm_dirlist,params);
1280 myfree(labname);
1281 continue;
1282 }
1283 else {
1284 /* it's just a label */
1285 label = new_labsym(0,labname);
1286 add_atom(0,new_label_atom(label));
1287 }
1288
1289 if (!is_local_label(labname) && autoexport)
1290 label->flags |= EXPORT;
1291 myfree(labname);
1292 }
1293
1294 /* check for directives first */
1295 s = skip(s);
1296 if (*s==commentchar)
1297 continue;
1298
1299 s = parse_cpu_special(s);
1300 if (ISEOL(s))
1301 continue;
1302
1303 if (*s==current_pc_char && *(s+1)=='=') { /* "*=" org directive */
1304 handle_org(skip(s+2));
1305 continue;
1306 }
1307 if (handle_directive(s))
1308 continue;
1309
1310 s = skip(s);
1311 if (ISEOL(s))
1312 continue;
1313
1314 /* read mnemonic name */
1315 inst = s;
1316 ext_cnt = 0;
1317 if (!ISIDSTART(*s)) {
1318 syntax_error(10); /* identifier expected */
1319 continue;
1320 }
1321 #if MAX_QUALIFIERS==0
1322 while (*s && !isspace((unsigned char)*s))
1323 s++;
1324 inst_len = s - inst;
1325 #else
1326 s = parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt);
1327 #endif
1328 if (!isspace((unsigned char)*s) && *s!='\0')
1329 syntax_error(2); /* no space before operands */
1330 s = skip(s);
1331
1332 if (execute_macro(inst,inst_len,ext,ext_len,ext_cnt,s))
1333 continue;
1334 if (execute_struct(inst,inst_len,s))
1335 continue;
1336
1337 /* read operands, terminated by comma or blank (unless in parentheses) */
1338 op_cnt = 0;
1339 while (!ISEOL(s) && op_cnt<MAX_OPERANDS) {
1340 op[op_cnt] = s;
1341 s = skip_oper(1,s);
1342 op_len[op_cnt] = oplen(s,op[op_cnt]);
1343 #if !ALLOW_EMPTY_OPS
1344 if (op_len[op_cnt] <= 0)
1345 syntax_error(5); /* missing operand */
1346 else
1347 #endif
1348 op_cnt++;
1349
1350 if (igntrail) {
1351 if (*s != ',')
1352 break;
1353 s++;
1354 }
1355 else {
1356 s = skip(s);
1357 if (OPERSEP_COMMA) {
1358 if (*s == ',')
1359 s = skip(s+1);
1360 else if (!(OPERSEP_BLANK))
1361 break;
1362 }
1363 }
1364 }
1365 eol(s);
1366
1367 ip = new_inst(inst,inst_len,op_cnt,op,op_len);
1368
1369 #if MAX_QUALIFIERS>0
1370 if (ip) {
1371 int i;
1372
1373 for (i=0; i<ext_cnt; i++)
1374 ip->qualifiers[i] = cnvstr(ext[i],ext_len[i]);
1375 for(; i<MAX_QUALIFIERS; i++)
1376 ip->qualifiers[i] = NULL;
1377 }
1378 #endif
1379
1380 if (ip)
1381 add_atom(0,new_inst_atom(ip));
1382 }
1383
1384 cond_check();
1385 }
1386
1387
1388 /* parse next macro argument */
1389 char *parse_macro_arg(struct macro *m,char *s,
1390 struct namelen *param,struct namelen *arg)
1391 {
1392 arg->len = 0; /* cannot select specific named arguments */
1393 param->name = s;
1394
1395 if (*s=='\"' || *s=='\'') {
1396 s = skip_string(s,*s,NULL);
1397 param->len = s - param->name;
1398 }
1399 else {
1400 s = skip_operand(s);
1401 param->len = s - param->name;
1402 }
1403
1404 return s;
1405 }
1406
1407
1408 /* expands arguments and special escape codes into macro context */
1409 int expand_macro(source *src,char **line,char *d,int dlen)
1410 {
1411 int nc = 0;
1412 int n;
1413 char *s = *line;
1414 char *end;
1415
1416 if (*s++ == '\\') {
1417 /* possible macro expansion detected */
1418
1419 if (*s == '\\') {
1420 if (dlen >= 1) {
1421 *d++ = *s++;
1422 if (esc_sequences) {
1423 if (dlen >= 2) {
1424 *d++ = '\\'; /* make it a double \ again */
1425 nc = 2;
1426 }
1427 else
1428 nc = -1;
1429 }
1430 else
1431 nc = 1;
1432 }
1433 else
1434 nc = -1;
1435 }
1436
1437 else if (*s == '@') {
1438 /* \@: insert a unique id */
1439 nc = snprintf(d,dlen,"_%06lu",src->id);
1440 s++;
1441 if (nc >= dlen)
1442 nc = -1;
1443 }
1444 else if (*s=='(' && *(s+1)==')') {
1445 /* \() is just skipped, useful to terminate named macro parameters */
1446 nc = 0;
1447 s += 2;
1448 }
1449 else if (*s == '<') {
1450 /* \<symbol> : insert absolute unsigned symbol value */
1451 char *name;
1452 symbol *sym;
1453 taddr val;
1454
1455 s++;
1456 if (name = parse_symbol(&s)) {
1457 if ((sym = find_symbol(name)) && sym->type==EXPRESSION) {
1458 if (eval_expr(sym->expr,&val,NULL,0))
1459 nc = sprintf(d,"%lu",(unsigned long)(uint32_t)val);
1460 }
1461 myfree(name);
1462 if (*s++!='>' || nc<0) {
1463 syntax_error(11); /* invalid numeric expansion */
1464 return 0;
1465 }
1466 }
1467 else {
1468 syntax_error(10); /* identifier expected */
1469 return 0;
1470 }
1471 }
1472 else if (isdigit((unsigned char)*s)) {
1473 /* \1..\9,\0 : insert macro parameter 1..9,10 */
1474 nc = copy_macro_param(src,*s=='0'?0:*s-'1',d,dlen);
1475 s++;
1476 }
1477 else if ((end = skip_identifier(s)) != NULL) {
1478 if ((n = find_macarg_name(src,s,end-s)) >= 0) {
1479 /* \argname: insert named macro parameter n */
1480 nc = copy_macro_param(src,n,d,dlen);
1481 s = end;
1482 }
1483 }
1484
1485 if (nc >= 0)
1486 *line = s; /* update line pointer when expansion took place */
1487 }
1488
1489 return nc; /* number of chars written to line buffer, -1: out of space */
1490 }
1491
1492
1493 static int intel_suffix(char *s)
1494 /* check for constants with h, d, o, q or b suffix */
1495 {
1496 int base,lastbase;
1497 char c;
1498
1499 base = 2;
1500 while (isxdigit((unsigned char)*s)) {
1501 lastbase = base;
1502 switch (base) {
1503 case 2:
1504 if (*s <= '1') break;
1505 base = 8;
1506 case 8:
1507 if (*s <= '7') break;
1508 base = 10;
1509 case 10:
1510 if (*s <= '9') break;
1511 base = 16;
1512 }
1513 s++;
1514 }
1515
1516 c = tolower((unsigned char)*s);
1517 if (c == 'h')
1518 return 16;
1519 if ((c=='o' || c=='q') && base<=8)
1520 return 8;
1521
1522 c = tolower((unsigned char)*(s-1));
1523 if (c=='d' && lastbase<=10)
1524 return 10;
1525 if (c=='b' && lastbase<=2)
1526 return 2;
1527
1528 return 0;
1529 }
1530
1531
1532 char *const_prefix(char *s,int *base)
1533 {
1534 if (isdigit((unsigned char)*s)) {
1535 if (!nointelsuffix && (*base = intel_suffix(s)))
1536 return s;
1537 if (!nocprefix) {
1538 if (*s == '0') {
1539 if (s[1]=='x' || s[1]=='X'){
1540 *base = 16;
1541 return s+2;
1542 }
1543 if (s[1]=='b' || s[1]=='B'){
1544 *base = 2;
1545 return s+2;
1546 }
1547 *base = 8;
1548 return s;
1549 }
1550 else if (s[1]=='#' && *s>='2' && *s<='9') {
1551 *base = *s & 0xf;
1552 return s+2;
1553 }
1554 }
1555 *base = 10;
1556 return s;
1557 }
1558
1559 if (*s=='$' && isxdigit((unsigned char)s[1])) {
1560 *base = 16;
1561 return s+1;
1562 }
1563 #if defined(VASM_CPU_Z80)
1564 if ((*s=='&' || *s=='#') && isxdigit((unsigned char)s[1])) {
1565 *base = 16;
1566 return s+1;
1567 }
1568 #endif
1569 if (*s=='@') {
1570 #if defined(VASM_CPU_Z80)
1571 *base = 2;
1572 #else
1573 *base = 8;
1574 #endif
1575 return s+1;
1576 }
1577 if (*s == '%') {
1578 *base = 2;
1579 return s+1;
1580 }
1581 *base = 0;
1582 return s;
1583 }
1584
1585
1586 char *const_suffix(char *start,char *end)
1587 {
1588 if (intel_suffix(start))
1589 return end+1;
1590
1591 return end;
1592 }
1593
1594
1595 static char *skip_local(char *p)
1596 {
1597 char *s;
1598
1599 if (ISIDSTART(*p) || isdigit((unsigned char)*p)) { /* may start with digit */
1600 s = p++;
1601 while (ISIDCHAR(*p))
1602 p++;
1603 }
1604 else
1605 p = NULL;
1606
1607 return p;
1608 }
1609
1610
1611 char *get_local_label(char **start)
1612 /* Local labels start with a '.' or end with '$': "1234$", ".1" */
1613 {
1614 char *s,*p,*name;
1615
1616 name = NULL;
1617 s = *start;
1618 p = skip_local(s);
1619
1620 if (p!=NULL && *p=='.' && ISIDCHAR(*(p+1)) &&
1621 ISIDSTART(*s) && *s!='.' && *(p-1)!='$') {
1622 /* skip local part of global.local label */
1623 s = p + 1;
1624 p = skip_local(p);
1625 name = make_local_label(*start,(s-1)-*start,s,p-s);
1626 *start = skip(p);
1627 }
1628 else if (p!=NULL && p>(s+1) && *s=='.') { /* .label */
1629 s++;
1630 name = make_local_label(NULL,0,s,p-s);
1631 *start = skip(p);
1632 }
1633 else if (p!=NULL && p>s && *p=='$') { /* label$ */
1634 p++;
1635 name = make_local_label(NULL,0,s,p-s);
1636 *start = skip(p);
1637 }
1638
1639 return name;
1640 }
1641
1642
1643 int init_syntax()
1644 {
1645 size_t i;
1646 hashdata data;
1647
1648 dirhash = new_hashtable(0x200); /* @@@ */
1649 for (i=0; i<dir_cnt; i++) {
1650 data.idx = i;
1651 add_hashentry(dirhash,directives[i].name,data);
1652 }
1653
1654 cond_init();
1655 set_internal_abs(REPTNSYM,-1); /* reserve the REPTN symbol */
1656 current_pc_char = '*';
1657
1658 if (orgmode != ~0)
1659 set_section(new_org(orgmode));
1660 return 1;
1661 }
1662
1663
1664 int syntax_args(char *p)
1665 {
1666 if (!strcmp(p,"-dotdir")) {
1667 dotdirs = 1;
1668 return 1;
1669 }
1670 else if (!strcmp(p,"-autoexp")) {
1671 autoexport = 1;
1672 return 1;
1673 }
1674 else if (!strncmp(p,"-org=",5)) {
1675 orgmode = atoi(p+5);
1676 return 1;
1677 }
1678 else if (OPERSEP_COMMA && !strcmp(p,"-i")) {
1679 igntrail = 1;
1680 return 1;
1681 }
1682 else if (!strcmp(p,"-noc")) {
1683 nocprefix = 1;
1684 return 1;
1685 }
1686 else if (!strcmp(p,"-noi")) {
1687 nointelsuffix = 1;
1688 return 1;
1689 }
1690 return 0;
1691 }
1692