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