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