INSTALL: Add missing word 'install' to the example of putting the compiled targets...
[linux-libre-firmware.git] / a56 / main.c
1 /*******************************************************
2  *
3  *  a56 - a DSP56001 assembler
4  *
5  *  Written by Quinn C. Jensen
6  *  July 1990
7  *
8  *******************************************************\
9
10 /*
11  * Copyright (C) 1990-1994 Quinn C. Jensen
12  *
13  * Permission to use, copy, modify, distribute, and sell this software
14  * and its documentation for any purpose is hereby granted without fee,
15  * provided that the above copyright notice appear in all copies and
16  * that both that copyright notice and this permission notice appear
17  * in supporting documentation.  The author makes no representations
18  * about the suitability of this software for any purpose.  It is
19  * provided "as is" without express or implied warranty.
20  *
21  */
22 static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
23
24 /*
25  *  main.c - The "main" code for the assembler.
26  *
27  */
28
29 #include "a56.h"
30
31 #define MAX 1024
32
33 int pass;
34 int error, warning;
35 extern unsigned long pc;
36 extern int seg;
37 BOOL binary_listing = FALSE;
38 BOOL list_includes = FALSE;
39 FILE *obj = NULL;
40 extern BOOL list_on;
41 BOOL list_on_next = TRUE;
42 char *alloc();
43
44 main(argc,argv)
45 int argc;
46 char *argv[];
47 {
48         int i;
49         extern char *optarg;
50         extern int optind;
51         int c;
52         char *output_file = "a56.out";
53         char *input_file;
54         char *usage = "usage: a56  [-b]  [-l]  [-d]  [-o output-file]  input-file\n";
55
56         while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) {
57                 case 'b':
58                         binary_listing++;
59                         break;
60                 case 'l':
61                         list_includes++;
62                         break;
63                 case 'd':
64                         ldebug++;
65                         break;
66                 case 'o':
67                         output_file = optarg;
68                         break;
69                 case '?':
70                 default:
71                         fatal(usage);
72         }
73         input_file = argv[optind++];
74         if(input_file == NULL) fatal(usage);
75         obj = open_write(output_file);
76
77         pc = 0;
78         seg = 0;
79         pass = 1;
80         reset_psects();
81         include(input_file);
82
83         pc = 0;
84         seg = 0;
85         pass = 2;
86         reset_psects();
87         include(input_file);
88
89         psect_summary();
90         dump_symtab();
91         fclose(obj);
92         printf("errors=%d\n", error);
93         printf("warnings=%d\n", warning);
94         return error ? 1 : 0;
95 }
96
97 struct inc inc[MAX_NEST];
98 int inc_p = 0;
99 FILE *yyin;
100
101 include(file)
102 char *file;
103 {
104         FILE *fp = open_read(file);
105
106         inc_p++;
107         if(inc_p >= MAX_NEST)
108                 fatal("%s: include nesting too deep\n", file);
109
110         inc[inc_p].file = file;
111         inc[inc_p].fp = fp;
112         inc[inc_p].line = 1;
113
114         list_on_next = TRUE;
115         if(inc_p > 1 && NOT list_includes)
116                 list_on_next = FALSE;
117
118         yyin = inc[inc_p].fp;
119         if(inc_p == 1)
120 #ifdef FLEX
121         {
122                 static int started = 0;
123                 if(started)
124                         yyrestart(yyin);
125                 else
126                         started = 1;
127                 yyparse();
128         }
129 #else
130                 yyparse();
131 #endif
132 }
133
134 yywrap()
135 {
136         fclose(inc[inc_p].fp);
137         inc_p--;
138         list_on = list_on_next = TRUE;
139         if(inc_p > 1)
140                 list_on = list_on_next = FALSE;
141         if(inc_p) {
142                 yyin = inc[inc_p].fp;
143                 return 0;
144         } else {
145                 return 1;
146         }
147 }
148
149 struct n
150 sym_ref(sym)            /* return symbol value or UNDEF if not defined yet */
151 char *sym;
152 {
153         struct sym *sp, *find_sym();
154         struct n result;
155
156         result.type = UNDEF;
157
158         sp = find_sym(sym);
159         if(NOT sp) {
160                 if(pass == 2) {
161                         yyerror("%s: undefined symbol", sym);
162                 }                  
163                 return result;
164         }
165
166         return sp->n;
167 }
168
169 #define HASHSIZE 128
170
171 #define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE)
172
173 struct sym *symtab[HASHSIZE];
174
175 sym_def(sym, type, seg, i, f)
176 char *sym;
177 int type;
178 int seg;
179 int i;
180 double f;
181 {
182         struct sym *sp, **stop, *find_sym();
183
184         if(pass == 1) {
185                 if(find_sym(sym)) {
186                         pass = 2;                               /* what a kludge */
187                         yyerror("%s: multiply defined symbol", sym);
188                         pass = 1;
189                         return;
190                 }
191                 stop = &symtab[HASH(sym)];
192                 sp = NEW(struct sym);
193                 sp->next = *stop;
194                 *stop = sp;
195                 sp->name = strsave(sym);
196                 sp->n.type = type;
197                 sp->n.seg = seg;
198                 if(type == INT)
199                         sp->n.val.i = i & 0xFFFFFF;
200                 else
201                         sp->n.val.f = f;
202         } else {
203                 sp = find_sym(sym);
204                 if(NOT sp)
205                         fatal("internal error 304\n");
206                 if(sp->n.type != type ||
207                         type == INT && sp->n.val.i != (i & 0xFFFFFF) ||
208                         type == FLT && sp->n.val.f != f)
209                         yyerror("%s: assembler phase error", sym);
210         }               
211 }
212
213 struct sym *find_sym(sym)
214 char *sym;
215 {
216         struct sym *sp, **stop;
217
218         stop = &symtab[HASH(sym)];
219         for(sp = *stop; sp; sp = sp->next)
220                 if(strcmp(sp->name, sym) == 0)
221                         return sp;
222                 
223         return NULL;
224 }
225
226 extern char segs[];
227 dump_symtab()
228 {
229         struct sym *sp, **stop;
230         int i;
231
232         printf("\n\
233 Symbol Table\n\
234 -------------------------------------\n");
235 /*
236 SSSSSSSSSSSSSSSS S XXXXXX
237 SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD
238 */
239
240         for(i = 0, stop = symtab; i < HASHSIZE; i++, stop++) {
241                 for(sp = *stop; sp; sp = sp->next) {
242                         if(sp->n.type == INT) {
243                                 printf("%16s %c %06X\n", sp->name, segs[sp->n.seg], sp->n.val.i);
244                                 fprintf(obj, "I %06X %s\n", sp->n.val.i, sp->name);
245                         } else {
246                                 printf("%16s %c %.10f\n", sp->name, segs[sp->n.seg], sp->n.val.f);
247                                 fprintf(obj, "F %.10f %s\n", sp->n.val.f, sp->name);
248                         }
249                 }
250         }   
251 }
252
253 char *printcode(word)
254 int word;
255 {
256         static char list[MAX], *lp;
257         int i;
258
259         word &= 0xFFFFFF;
260
261         if(binary_listing) {
262                 sprintf(list, "%06X<", word);
263                 for(i = 0, lp = &list[7]; i < 24; i++, lp++) {
264                         *lp = word & 1 << 23 - i ? '1' : '0';
265                         if(i && i % 4 == 3)
266                                 *++lp = i % 8 == 7 ? ' ' : ',';
267                 }
268                 lp[-1] = '>';
269                 lp[0] = '\0';
270         } else {
271                 sprintf(list, "%06X", word);
272         }
273         return list;
274 }
275
276 char *spacespace[2] = {
277 /*P:XXXX_XXXXXX_*/
278  "              ",
279 /*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/
280  "                                             "};
281 char *spaces(n)
282 int n;
283 {
284         return spacespace[binary_listing ? 1 : 0] + n;
285 }
286
287 extern char segs[];
288
289 gencode(seg, pc, word)
290 int seg, pc, word;
291 {
292         fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF);
293 }
294
295 char fixbuf[1024];
296
297 char *fixstring(s)
298 char *s;
299 {
300         char *bp = fixbuf;
301         int ival;
302
303         while(*s) {
304                 switch (*s) {
305                         case '\'':
306                         case '\"':
307                                 s++;
308                                 break;
309                         case '\\':
310                                 switch (*++s) {
311                                         case 'b': *bp++ = '\b'; break;
312                                         case 'r': *bp++ = '\r'; break;
313                                         case 'f': *bp++ = '\f'; break;
314                                         case 'n': *bp++ = '\n'; break;
315                                         case 't': *bp++ = '\t'; break;
316                                         case '\\': *bp++ = '\\'; break;
317                                         case '0':
318                                                 ival = 0;
319                                                 while(*s >= '0' && *s <= '9') {
320                                                         ival <<= 3;
321                                                         ival += *s++ - '0';
322                                                 }
323                                                 *bp++ = ival;
324                                                 break;
325                                 }
326                                 break;
327                         default:
328                                 *bp++ = *s++;
329                                 break;
330                 }
331         }
332         *bp = '\0';
333         return fixbuf;
334 }
335
336 #define ONE 0x4000000
337
338 makefrac(s)
339 char *s;
340 {
341         int frac = 0, div = 1;
342         int scale = 1;
343
344         while(*s) {
345                 switch(*s) {
346                         case '-':
347                                 scale = -1;
348                                 break;
349                         case '.':
350                                 div = 10;
351                                 break;
352                         default:
353                                 frac += (*s - '0') * scale * ONE / div;
354                                 div *= 10;
355                                 break;
356                 }
357                 s++;
358         }
359
360         return frac + scale * 4 >> 3 & 0xFFFFFF;
361 }
362
363 /***************** psect stuff ************************/
364
365 struct psect *ptop = NULL, *cur_psect = NULL;
366
367 reset_psects()
368 {
369         struct psect *pp;
370
371         for(pp = ptop; pp; pp = pp->next) {
372                 pp->pc = pp->bottom;
373         }
374
375         set_psect(NULL);
376 }
377
378 psect_summary()
379 {
380         printf("\nSummary of psect usage\n\n");
381
382         printf("\
383                  section seg base last top      used       avail    total\n\
384 -------------------------------------------------------------------------\n");
385 /*
386 SSSSSSSSSSSSSSSSSSSSSSSS  X  FFFF FFFF FFFF 99999 100%  99999 100%  99999
387 */
388
389         summarize(ptop);        /* do it recursively to place back in order */
390         printf("\n");
391 }
392
393 summarize(pp)
394 struct psect *pp;
395 {
396         int used, avail, of;
397
398         if(pp == NULL)
399                 return;
400
401         used = pp->pc - pp->bottom;
402         avail = pp->top - pp->pc;
403         of = pp->top - pp->bottom;
404
405         summarize(pp->next);
406
407         printf("%24.24s  %c  %04X %04X %04X %5d %3d%%  %5d %3d%%  %5d\n",
408                 pp->name, segs[pp->seg], pp->bottom, pp->pc, pp->top,
409                 used, of ? used * 100 / of : 0, avail, of ? avail * 100 / of : 0,
410                 of);
411 }
412
413 struct psect *find_psect(name)
414 char *name;
415 {
416         struct psect *pp;
417
418         for(pp = ptop; pp; pp = pp->next)
419                 if(strcmp(pp->name, name) == 0)
420                         return pp;
421
422         return NULL;
423 }
424
425 set_psect(pp)
426 struct psect *pp;
427 {
428         cur_psect = pp;
429 }
430
431 check_psect(seg, pc)
432 int seg;
433 unsigned int pc;
434 {
435         if(cur_psect) {
436                 if(seg == cur_psect->seg && pc >= cur_psect->bottom && 
437                         pc <= cur_psect->top) {
438                         cur_psect->pc = pc;
439                         return TRUE;
440                 } else {
441                         return FALSE;
442                 }
443         } else {
444                 return TRUE;
445         }
446 }
447
448 struct psect *new_psect(name, seg, bottom, top)
449 char *name;
450 int seg;
451 unsigned int bottom, top;
452 {
453         struct psect *pp = find_psect(name);
454
455         if(NOT pp) {
456                 pp = (struct psect *)alloc(sizeof *pp);
457                 pp->next = ptop;
458                 ptop = pp;
459                 pp->name = strsave(name);
460                 pp->seg = seg;
461                 pp->pc = bottom;
462         }
463         pp->bottom = bottom;
464         pp->top = top;
465
466         return pp;
467 }