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>
13 * Copyright (C) 2014 Arthur Marble <arthur@info9.net>
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.
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.
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/>.
29 * This file incorporates work covered by the following copyright and
32 * Copyright (C) 1990-1994 Quinn C. Jensen
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.
43 static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
46 * main.c - The "main" code for the assembler.
56 extern unsigned int pc;
58 BOOL binary_listing = FALSE;
59 BOOL list_includes = FALSE;
62 BOOL list_on_next = TRUE;
72 char *output_file = "a56.out";
74 char *usage = "usage: a56 [-b] [-l] [-d] [-o output-file] input-file\n";
76 while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) {
93 input_file = argv[optind++];
94 if(input_file == NULL) fatal(usage);
95 obj = open_write(output_file);
112 printf("errors=%d\n", error);
113 printf("warnings=%d\n", warning);
114 return error ? 1 : 0;
117 struct inc inc[MAX_NEST];
124 FILE *fp = open_read(file);
127 if(inc_p >= MAX_NEST)
128 fatal("%s: include nesting too deep\n", file);
130 inc[inc_p].file = file;
135 if(inc_p > 1 && NOT list_includes)
136 list_on_next = FALSE;
138 yyin = inc[inc_p].fp;
142 static int started = 0;
156 fclose(inc[inc_p].fp);
158 list_on = list_on_next = TRUE;
160 list_on = list_on_next = FALSE;
162 yyin = inc[inc_p].fp;
170 sym_ref(sym) /* return symbol value or UNDEF if not defined yet */
173 struct sym *sp, *find_sym();
181 yyerror("%s: undefined symbol", sym);
191 #define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE)
193 struct sym *symtab[HASHSIZE];
195 sym_def(sym, type, seg, i, f)
202 struct sym *sp, **stop, *find_sym();
206 pass = 2; /* what a kludge */
207 yyerror("%s: multiply defined symbol", sym);
211 stop = &symtab[HASH(sym)];
212 sp = NEW(struct sym);
215 sp->name = strsave(sym);
219 sp->n.val.i = i & 0xFFFFFF;
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);
233 struct sym *find_sym(sym)
236 struct sym *sp, **stop;
238 stop = &symtab[HASH(sym)];
239 for(sp = *stop; sp; sp = sp->next)
240 if(strcmp(sp->name, sym) == 0)
249 struct sym *sp, **stop;
254 -------------------------------------\n");
256 SSSSSSSSSSSSSSSS S XXXXXX
257 SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD
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);
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);
273 char *printcode(word)
276 static char list[MAX], *lp;
282 sprintf(list, "%06X<", word);
283 for(i = 0, lp = &list[7]; i < 24; i++, lp++) {
284 *lp = word & 1 << 23 - i ? '1' : '0';
286 *++lp = i % 8 == 7 ? ' ' : ',';
291 sprintf(list, "%06X", word);
296 char *spacespace[2] = {
299 /*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/
304 return spacespace[binary_listing ? 1 : 0] + n;
309 gencode(seg, pc, word)
312 fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF);
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;
339 while(*s >= '0' && *s <= '9') {
356 #define ONE 0x4000000
361 int frac = 0, div = 1;
373 frac += (*s - '0') * scale * ONE / div;
380 return frac + scale * 4 >> 3 & 0xFFFFFF;
383 /***************** psect stuff ************************/
385 struct psect *ptop = NULL, *cur_psect = NULL;
391 for(pp = ptop; pp; pp = pp->next) {
400 printf("\nSummary of psect usage\n\n");
403 section seg base last top used avail total\n\
404 -------------------------------------------------------------------------\n");
406 SSSSSSSSSSSSSSSSSSSSSSSS X FFFF FFFF FFFF 99999 100% 99999 100% 99999
409 summarize(ptop); /* do it recursively to place back in order */
421 used = pp->pc - pp->bottom;
422 avail = pp->top - pp->pc;
423 of = pp->top - pp->bottom;
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,
433 struct psect *find_psect(name)
438 for(pp = ptop; pp; pp = pp->next)
439 if(strcmp(pp->name, name) == 0)
456 if(seg == cur_psect->seg && pc >= cur_psect->bottom &&
457 pc <= cur_psect->top) {
468 struct psect *new_psect(name, seg, bottom, top)
471 unsigned int bottom, top;
473 struct psect *pp = find_psect(name);
476 pp = (struct psect *)alloc(sizeof *pp);
479 pp->name = strsave(name);