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