1 /*******************************************************
3 * a56 - a DSP56001 assembler
5 * Written by Quinn C. Jensen
8 *******************************************************\
11 * Copyright (C) 2008 Robert Millan <rmh@aybabtu.com>
12 * Copyright (C) 2012 Thorsten Alteholz <debian@alteholz.de>
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.
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.
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/>.
28 * This file incorporates work covered by the following copyright and
31 * Copyright (C) 1990-1994 Quinn C. Jensen
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.
42 static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
45 * main.c - The "main" code for the assembler.
55 extern unsigned int pc;
57 BOOL binary_listing = FALSE;
58 BOOL list_includes = FALSE;
61 BOOL list_on_next = TRUE;
71 char *output_file = "a56.out";
73 char *usage = "usage: a56 [-b] [-l] [-d] [-o output-file] input-file\n";
75 while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) {
92 input_file = argv[optind++];
93 if(input_file == NULL) fatal(usage);
94 obj = open_write(output_file);
111 printf("errors=%d\n", error);
112 printf("warnings=%d\n", warning);
113 return error ? 1 : 0;
116 struct inc inc[MAX_NEST];
123 FILE *fp = open_read(file);
126 if(inc_p >= MAX_NEST)
127 fatal("%s: include nesting too deep\n", file);
129 inc[inc_p].file = file;
134 if(inc_p > 1 && NOT list_includes)
135 list_on_next = FALSE;
137 yyin = inc[inc_p].fp;
141 static int started = 0;
155 fclose(inc[inc_p].fp);
157 list_on = list_on_next = TRUE;
159 list_on = list_on_next = FALSE;
161 yyin = inc[inc_p].fp;
169 sym_ref(sym) /* return symbol value or UNDEF if not defined yet */
172 struct sym *sp, *find_sym();
180 yyerror("%s: undefined symbol", sym);
190 #define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE)
192 struct sym *symtab[HASHSIZE];
194 sym_def(sym, type, seg, i, f)
201 struct sym *sp, **stop, *find_sym();
205 pass = 2; /* what a kludge */
206 yyerror("%s: multiply defined symbol", sym);
210 stop = &symtab[HASH(sym)];
211 sp = NEW(struct sym);
214 sp->name = strsave(sym);
218 sp->n.val.i = i & 0xFFFFFF;
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);
232 struct sym *find_sym(sym)
235 struct sym *sp, **stop;
237 stop = &symtab[HASH(sym)];
238 for(sp = *stop; sp; sp = sp->next)
239 if(strcmp(sp->name, sym) == 0)
248 struct sym *sp, **stop;
253 -------------------------------------\n");
255 SSSSSSSSSSSSSSSS S XXXXXX
256 SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD
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);
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);
272 char *printcode(word)
275 static char list[MAX], *lp;
281 sprintf(list, "%06X<", word);
282 for(i = 0, lp = &list[7]; i < 24; i++, lp++) {
283 *lp = word & 1 << 23 - i ? '1' : '0';
285 *++lp = i % 8 == 7 ? ' ' : ',';
290 sprintf(list, "%06X", word);
295 char *spacespace[2] = {
298 /*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/
303 return spacespace[binary_listing ? 1 : 0] + n;
308 gencode(seg, pc, word)
311 fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF);
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;
338 while(*s >= '0' && *s <= '9') {
355 #define ONE 0x4000000
360 int frac = 0, div = 1;
372 frac += (*s - '0') * scale * ONE / div;
379 return frac + scale * 4 >> 3 & 0xFFFFFF;
382 /***************** psect stuff ************************/
384 struct psect *ptop = NULL, *cur_psect = NULL;
390 for(pp = ptop; pp; pp = pp->next) {
399 printf("\nSummary of psect usage\n\n");
402 section seg base last top used avail total\n\
403 -------------------------------------------------------------------------\n");
405 SSSSSSSSSSSSSSSSSSSSSSSS X FFFF FFFF FFFF 99999 100% 99999 100% 99999
408 summarize(ptop); /* do it recursively to place back in order */
420 used = pp->pc - pp->bottom;
421 avail = pp->top - pp->pc;
422 of = pp->top - pp->bottom;
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,
432 struct psect *find_psect(name)
437 for(pp = ptop; pp; pp = pp->next)
438 if(strcmp(pp->name, name) == 0)
455 if(seg == cur_psect->seg && pc >= cur_psect->bottom &&
456 pc <= cur_psect->top) {
467 struct psect *new_psect(name, seg, bottom, top)
470 unsigned int bottom, top;
472 struct psect *pp = find_psect(name);
475 pp = (struct psect *)alloc(sizeof *pp);
478 pp->name = strsave(name);