1 /* atom.c - atomic objects from source */
2 /* (c) in 2010-2018 by Volker Barthelmann and Frank Wille */
3 
4 #include "vasm.h"
5 
6 
7 /* searches mnemonic list and tries to parse (via the cpu module)
8    the operands according to the mnemonic requirements; returns an
9    instruction or 0 */
new_inst(char * inst,int len,int op_cnt,char ** op,int * op_len)10 instruction *new_inst(char *inst,int len,int op_cnt,char **op,int *op_len)
11 {
12 #if MAX_OPERANDS!=0
13   operand ops[MAX_OPERANDS];
14   int j,k,mnemo_opcnt,omitted,skipped;
15 #endif
16   int i,inst_found=0;
17   hashdata data;
18   instruction *new;
19 
20   new = mymalloc(sizeof(*new));
21 #if HAVE_INSTRUCTION_EXTENSION
22   init_instruction_ext(&new->ext);
23 #endif
24 #if MAX_OPERANDS!=0 && NEED_CLEARED_OPERANDS!=0
25   /* reset operands to allow the cpu-backend to parse them only once */
26   memset(ops,0,sizeof(ops));
27 #endif
28 
29   if (find_namelen_nc(mnemohash,inst,len,&data)) {
30     i = data.idx;
31 
32     /* try all mnemonics with the same name until operands match */
33     do {
34       inst_found = 1;
35       if (!MNEMONIC_VALID(i)) {
36         i++;
37         continue;  /* try next */
38       }
39 
40 #if MAX_OPERANDS!=0
41 
42 #if ALLOW_EMPTY_OPS
43       mnemo_opcnt = op_cnt<MAX_OPERANDS ? op_cnt : MAX_OPERANDS;
44 #else
45       for (j=0; j<MAX_OPERANDS; j++)
46         if (mnemonics[i].operand_type[j] == 0)
47           break;
48       mnemo_opcnt = j;	/* number of expected operands for this mnemonic */
49 #endif
50       inst_found = 2;
51       save_symbols();  /* make sure we can restore symbols to this point */
52 
53       for (j=k=omitted=skipped=0; j<mnemo_opcnt; j++) {
54 
55         if (op_cnt+omitted < mnemo_opcnt &&
56             OPERAND_OPTIONAL(&ops[j],mnemonics[i].operand_type[j])) {
57           omitted++;
58         }
59         else {
60           int rc;
61 
62           if (k >= op_cnt)  /* missing mandatory operands */
63             break;
64 
65           rc = parse_operand(op[k],op_len[k],&ops[j],
66                                  mnemonics[i].operand_type[j]);
67 
68           if (rc == PO_CORRUPT) {
69             myfree(new);
70             restore_symbols();
71             return 0;
72           }
73           if (rc == PO_NOMATCH)
74               break;
75 
76           /* MATCH, move to next parsed operand */
77           k++;
78           if (rc == PO_SKIP) {	/* but skip next operand type from table */
79             j++;
80             skipped++;
81           }
82         }
83       }
84 
85 #if IGNORE_FIRST_EXTRA_OP
86       if (mnemo_opcnt > 0)
87 #endif
88       if (j<mnemo_opcnt || k<op_cnt) {
89         /* No match. Try next mnemonic. */
90         i++;
91         restore_symbols();
92         continue;
93       }
94 
95       /* Matched! Copy operands. */
96       mnemo_opcnt -= skipped;
97       for (j=0; j<mnemo_opcnt; j++) {
98         new->op[j] = mymalloc(sizeof(operand));
99         *new->op[j] = ops[j];
100       }
101       for(; j<MAX_OPERANDS; j++)
102         new->op[j] = 0;
103 
104 #endif /* MAX_OPERANDS!=0 */
105 
106       new->code = i;
107       return new;
108     }
109     while (i<mnemonic_cnt && !strnicmp(mnemonics[i].name,inst,len)
110            && mnemonics[i].name[len]==0);
111   }
112 
113   switch (inst_found) {
114     case 1:
115       general_error(8);  /* instruction not supported by cpu */
116       break;
117     case 2:
118       general_error(0);  /* illegal operand types */
119       break;
120     default:
121       general_error(1,cnvstr(inst,len));  /* completely unknown mnemonic */
122       break;
123   }
124   myfree(new);
125   return 0;
126 }
127 
128 
new_dblock(void)129 dblock *new_dblock(void)
130 {
131   dblock *new = mymalloc(sizeof(*new));
132 
133   new->size = 0;
134   new->data = 0;
135   new->relocs = 0;
136   return new;
137 }
138 
139 
new_sblock(expr * space,size_t size,expr * fill)140 sblock *new_sblock(expr *space,size_t size,expr *fill)
141 {
142   sblock *sb = mymalloc(sizeof(sblock));
143 
144   sb->space = 0;
145   sb->space_exp = space;
146   sb->size = size;
147   if (!(sb->fill_exp = fill))
148     memset(sb->fill,0,MAXPADBYTES);
149   sb->relocs = 0;
150   sb->maxalignbytes = 0;
151   return sb;
152 }
153 
154 
space_size(sblock * sb,section * sec,taddr pc)155 static size_t space_size(sblock *sb,section *sec,taddr pc)
156 {
157   utaddr space=0;
158 
159   if (eval_expr(sb->space_exp,&space,sec,pc) || !final_pass)
160     sb->space = space;
161   else
162     general_error(30);  /* expression must be constant */
163 
164   if (final_pass && sb->fill_exp) {
165     if (sb->size <= sizeof(taddr)) {
166       /* space is filled with an expression which may also need relocations */
167       symbol *base=NULL;
168       taddr fill;
169       utaddr i;
170 
171       if (!eval_expr(sb->fill_exp,&fill,sec,pc)) {
172         if (find_base(sb->fill_exp,&base,sec,pc)==BASE_ILLEGAL)
173           general_error(38);  /* illegal relocation */
174       }
175       copy_cpu_taddr(sb->fill,fill,sb->size);
176       if (base && !sb->relocs) {
177         /* generate relocations */
178         for (i=0; i<space; i++)
179           add_extnreloc(&sb->relocs,base,fill,REL_ABS,
180                         0,sb->size<<3,sb->size*i);
181       }
182     }
183     else
184       general_error(30);  /* expression must be constant */
185   }
186 
187   return sb->size * space;
188 }
189 
190 
roffs_size(expr * offsexp,section * sec,taddr pc)191 static size_t roffs_size(expr *offsexp,section *sec,taddr pc)
192 {
193   taddr offs;
194 
195   eval_expr(offsexp,&offs,sec,pc);
196   offs = sec->org + offs - pc;
197   return offs>0 ? offs : 0;
198 }
199 
200 
201 /* adds an atom to the specified section; if sec==0, the current
202    section is used */
add_atom(section * sec,atom * a)203 void add_atom(section *sec,atom *a)
204 {
205   if (!sec) {
206     sec = default_section();
207     if (!sec) {
208       general_error(3);
209       return;
210     }
211   }
212 
213   a->changes = 0;
214   a->src = cur_src;
215   a->line = cur_src!=NULL ? cur_src->line : 0;
216 
217   if (sec->last) {
218     atom *pa = sec->last;
219 
220     pa->next = a;
221     /* make sure that a label on the same line gets the same alignment */
222     if (pa->type==LABEL && pa->line==a->line &&
223         (a->type==INSTRUCTION || a->type==DATADEF || a->type==SPACE))
224       pa->align = a->align;
225   }
226   else
227     sec->first = a;
228   a->next = 0;
229   sec->last = a;
230 
231   sec->pc = pcalign(a,sec->pc);
232   a->lastsize = atom_size(a,sec,sec->pc);
233   sec->pc += a->lastsize;
234   if (a->align > sec->align)
235     sec->align = a->align;
236 
237   if (listena) {
238     a->list = last_listing;
239     if (last_listing) {
240       if (!last_listing->atom)
241         last_listing->atom = a;
242     }
243   }
244   else
245     a->list = 0;
246 }
247 
248 
atom_size(atom * p,section * sec,taddr pc)249 size_t atom_size(atom *p,section *sec,taddr pc)
250 {
251   switch(p->type) {
252     case LABEL:
253     case LINE:
254     case OPTS:
255     case PRINTTEXT:
256     case PRINTEXPR:
257     case RORG:
258     case RORGEND:
259     case ASSERT:
260     case NLIST:  /* it has a size, but not in the current section */
261       return 0;
262     case DATA:
263       return p->content.db->size;
264     case INSTRUCTION:
265       return p->content.inst->code>=0?
266              instruction_size(p->content.inst,sec,pc):0;
267     case SPACE:
268       return space_size(p->content.sb,sec,pc);
269     case DATADEF:
270       return (p->content.defb->bitsize+7)/8;
271     case ROFFS:
272       return roffs_size(p->content.roffs,sec,pc);
273     default:
274       ierror(0);
275       break;
276   }
277   return 0;
278 }
279 
280 
print_instruction(FILE * f,instruction * p)281 static void print_instruction(FILE *f,instruction *p)
282 {
283   int i;
284 
285   printf("inst %d(%s) ",p->code,p->code>=0?mnemonics[p->code].name:"deleted");
286 #if MAX_OPERANDS!=0
287   for (i=0; i<MAX_OPERANDS; i++)
288     printf("%p ",(void *)p->op[i]);
289 #endif
290 }
291 
292 
print_atom(FILE * f,atom * p)293 void print_atom(FILE *f,atom *p)
294 {
295   size_t i;
296   rlist *rl;
297 
298   switch (p->type) {
299     case LABEL:
300       fprintf(f,"symbol: ");
301       print_symbol(f,p->content.label);
302       break;
303     case DATA:
304       fprintf(f,"data(%lu): ",(unsigned long)p->content.db->size);
305       for (i=0;i<p->content.db->size;i++)
306         fprintf(f,"%02x ",p->content.db->data[i]);
307       for (rl=p->content.db->relocs; rl; rl=rl->next)
308         print_reloc(f,rl->type,rl->reloc);
309       break;
310     case INSTRUCTION:
311       print_instruction(f,p->content.inst);
312       break;
313     case SPACE:
314       fprintf(f,"space(%lu,fill=",
315               (unsigned long)(p->content.sb->space*p->content.sb->size));
316       for (i=0; i<p->content.sb->size; i++)
317         fprintf(f,"%02x%c",(unsigned char)p->content.sb->fill[i],
318                 (i==p->content.sb->size-1)?')':' ');
319       for (rl=p->content.sb->relocs; rl; rl=rl->next)
320         print_reloc(f,rl->type,rl->reloc);
321       break;
322     case DATADEF:
323       fprintf(f,"datadef(%lu bits)",(unsigned long)p->content.defb->bitsize);
324       break;
325     case LINE:
326       fprintf(f,"line: %d of %s",p->content.srcline,getdebugname());
327       break;
328 #if HAVE_CPU_OPTS
329     case OPTS:
330       print_cpu_opts(f,p->content.opts);
331       break;
332 #endif
333     case PRINTTEXT:
334       fprintf(f,"text: \"%s\"",p->content.ptext);
335       break;
336     case PRINTEXPR:
337       fprintf(f,"expr: ");
338       print_expr(f,p->content.pexpr->print_exp);
339       break;
340     case ROFFS:
341       fprintf(f,"roffs: offset ");
342       print_expr(f,p->content.roffs);
343       break;
344     case RORG:
345       fprintf(f,"rorg: relocate to 0x%llx",ULLTADDR(*p->content.rorg));
346       break;
347     case RORGEND:
348       fprintf(f,"rorg end");
349       break;
350     case ASSERT:
351       fprintf(f,"assert: %s (message: %s)\n",p->content.assert->expstr,
352               p->content.assert->msgstr?p->content.assert->msgstr:emptystr);
353       break;
354     case NLIST:
355       fprintf(f,"nlist: %s (type %d, other %d, desc %d) with value ",
356               p->content.nlist->name!=NULL ? p->content.nlist->name : "<NULL>",
357               p->content.nlist->type,p->content.nlist->other,
358               p->content.nlist->desc);
359       if (p->content.nlist->value != NULL)
360         print_expr(f,p->content.nlist->value);
361       else
362         fprintf(f,"NULL");
363       break;
364     default:
365       ierror(0);
366   }
367 }
368 
369 
370 /* prints and formats an expression from a PRINTEXPR atom */
atom_printexpr(printexpr * pexp,section * sec,taddr pc)371 void atom_printexpr(printexpr *pexp,section *sec,taddr pc)
372 {
373   taddr t;
374   long long v;
375   int i;
376 
377   eval_expr(pexp->print_exp,&t,sec,pc);
378   if (pexp->type==PEXP_SDEC && (t&(1LL<<(pexp->size-1)))!=0) {
379     /* signed decimal */
380     v = -1;
381     v &= ~(long long)MAKEMASK(pexp->size);
382   }
383   else
384     v = 0;
385   v |= t & MAKEMASK(pexp->size);
386 
387   switch (pexp->type) {
388     case PEXP_HEX:
389       printf("%llX",(unsigned long long)v);
390       break;
391     case PEXP_SDEC:
392       printf("%lld",v);
393       break;
394     case PEXP_UDEC:
395       printf("%llu",(unsigned long long)v);
396       break;
397     case PEXP_BIN:
398       for (i=pexp->size-1; i>=0; i--)
399         putchar((v & (1LL<<i)) ? '1' : '0');
400       break;
401     case PEXP_ASC:
402       for (i=((pexp->size+7)>>3)-1; i>=0; i--) {
403         unsigned char c = (v>>(i*8))&0xff;
404         putchar(isprint(c) ? c : '.');
405       }
406       break;
407     default:
408       ierror(0);
409       break;
410   }
411 }
412 
413 
clone_atom(atom * a)414 atom *clone_atom(atom *a)
415 {
416   atom *new = mymalloc(sizeof(atom));
417   void *p;
418 
419   memcpy(new,a,sizeof(atom));
420 
421   switch (a->type) {
422     /* INSTRUCTION and DATADEF have to be cloned as well, because they will
423        be deallocated and transformed into DATA during assemble() */
424     case INSTRUCTION:
425       p = mymalloc(sizeof(instruction));
426       memcpy(p,a->content.inst,sizeof(instruction));
427       new->content.inst = p;
428       break;
429     case DATADEF:
430       p = mymalloc(sizeof(defblock));
431       memcpy(p,a->content.defb,sizeof(defblock));
432       new->content.defb = p;
433       break;
434     default:
435       break;
436   }
437 
438   new->next = 0;
439   new->src = NULL;
440   new->line = 0;
441   new->list = NULL;
442   return new;
443 }
444 
445 
new_atom(int type,taddr align)446 static atom *new_atom(int type,taddr align)
447 {
448   atom *new = mymalloc(sizeof(*new));
449 
450   new->next = NULL;
451   new->type = type;
452   new->align = align;
453   return new;
454 }
455 
456 
new_inst_atom(instruction * p)457 atom *new_inst_atom(instruction *p)
458 {
459   atom *new = new_atom(INSTRUCTION,inst_alignment);
460 
461   new->content.inst = p;
462   return new;
463 }
464 
465 
new_data_atom(dblock * p,taddr align)466 atom *new_data_atom(dblock *p,taddr align)
467 {
468   atom *new = new_atom(DATA,align);
469 
470   new->content.db = p;
471   return new;
472 }
473 
474 
new_label_atom(symbol * p)475 atom *new_label_atom(symbol *p)
476 {
477   atom *new = new_atom(LABEL,1);
478 
479   new->content.label = p;
480   return new;
481 }
482 
483 
new_space_atom(expr * space,size_t size,expr * fill)484 atom *new_space_atom(expr *space,size_t size,expr *fill)
485 {
486   atom *new = new_atom(SPACE,1);
487   int i;
488 
489   if (size<1)
490     ierror(0);  /* usually an error in syntax-module */
491   new->content.sb = new_sblock(space,size,fill);
492   return new;
493 }
494 
495 
new_datadef_atom(size_t bitsize,operand * op)496 atom *new_datadef_atom(size_t bitsize,operand *op)
497 {
498   atom *new = new_atom(DATADEF,DATA_ALIGN(bitsize));
499 
500   new->content.defb = mymalloc(sizeof(*new->content.defb));
501   new->content.defb->bitsize = bitsize;
502   new->content.defb->op = op;
503   return new;
504 }
505 
506 
new_srcline_atom(int line)507 atom *new_srcline_atom(int line)
508 {
509   atom *new = new_atom(LINE,1);
510 
511   new->content.srcline = line;
512   return new;
513 }
514 
515 
new_opts_atom(void * o)516 atom *new_opts_atom(void *o)
517 {
518   atom *new = new_atom(OPTS,1);
519 
520   new->content.opts = o;
521   return new;
522 }
523 
524 
new_text_atom(char * txt)525 atom *new_text_atom(char *txt)
526 {
527   atom *new = new_atom(PRINTTEXT,1);
528 
529   new->content.ptext = txt ? txt : "\n";
530   return new;
531 }
532 
533 
new_expr_atom(expr * exp,int type,int size)534 atom *new_expr_atom(expr *exp,int type,int size)
535 {
536   atom *new = new_atom(PRINTEXPR,1);
537 
538   new->content.pexpr = mymalloc(sizeof(*new->content.pexpr));
539   if (exp==NULL || type<PEXP_HEX || type>PEXP_ASC || size<1
540       || size>sizeof(long long)*8)
541     ierror(0);
542   new->content.pexpr->print_exp = exp;
543   new->content.pexpr->type = type;
544   new->content.pexpr->size = size;
545   return new;
546 }
547 
548 
new_roffs_atom(expr * offs)549 atom *new_roffs_atom(expr *offs)
550 {
551   atom *new = new_atom(ROFFS,1);
552 
553   new->content.roffs = offs;
554   return new;
555 }
556 
557 
new_rorg_atom(taddr raddr)558 atom *new_rorg_atom(taddr raddr)
559 {
560   atom *new = new_atom(RORG,1);
561   taddr *newrorg = mymalloc(sizeof(taddr));
562 
563   *newrorg = raddr;
564   new->content.rorg = newrorg;
565   return new;
566 }
567 
568 
new_rorgend_atom(void)569 atom *new_rorgend_atom(void)
570 {
571   return new_atom(RORGEND,1);
572 }
573 
574 
new_assert_atom(expr * aexp,char * exp,char * msg)575 atom *new_assert_atom(expr *aexp,char *exp,char *msg)
576 {
577   atom *new = new_atom(ASSERT,1);
578 
579   new->content.assert = mymalloc(sizeof(*new->content.assert));
580   new->content.assert->assert_exp = aexp;
581   new->content.assert->expstr = exp;
582   new->content.assert->msgstr = msg;
583   return new;
584 }
585 
586 
new_nlist_atom(char * name,int type,int other,int desc,expr * value)587 atom *new_nlist_atom(char *name,int type,int other,int desc,expr *value)
588 {
589   atom *new = new_atom(NLIST,1);
590 
591   new->content.nlist = mymalloc(sizeof(*new->content.nlist));
592   new->content.nlist->name = name;
593   new->content.nlist->type = type;
594   new->content.nlist->other = other;
595   new->content.nlist->desc = desc;
596   new->content.nlist->value = value;
597   return new;
598 }
599