X-Git-Url: https://jxself.org/git/?p=a56.git;a=blobdiff_plain;f=src%2Fmain.c;fp=src%2Fmain.c;h=2d6b759c34f6fa58d37b92e34207235de208393d;hp=0000000000000000000000000000000000000000;hb=34923afb4a618598083726717bf2f20d310f4f6e;hpb=c6db6f4c5cb82f5e09472163bf11be0c165965ee diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..2d6b759 --- /dev/null +++ b/src/main.c @@ -0,0 +1,487 @@ +/******************************************************* + * + * a56 - a DSP56001 assembler + * + * Written by Quinn C. Jensen + * July 1990 + * + *******************************************************\ + +/* + * Copyright (C) 2008 Robert Millan + * Copyright (C) 2012 Thorsten Alteholz + * Copyright (C) 2014 Arthur Marble + * + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (C) 1990-1994 Quinn C. Jensen + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. The author makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. + * + */ +static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; + +/* + * main.c - The "main" code for the assembler. + * + */ + +#include "a56.h" + +#define MAX 1024 + +int pass; +int error, warning; +extern unsigned int pc; +extern int seg; +BOOL binary_listing = FALSE; +BOOL list_includes = FALSE; +FILE *obj = NULL; +extern BOOL list_on; +BOOL list_on_next = TRUE; + +main(argc,argv) +int argc; +char *argv[]; +{ + int i; + extern char *optarg; + extern int optind; + int c; + char *output_file = "a56.out"; + char *input_file; + char *usage = "usage: a56 [-b] [-l] [-d] [-o output-file] input-file\n"; + + while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) { + case 'b': + binary_listing++; + break; + case 'l': + list_includes++; + break; + case 'd': + ldebug++; + break; + case 'o': + output_file = optarg; + break; + case '?': + default: + fatal(usage); + } + input_file = argv[optind++]; + if(input_file == NULL) fatal(usage); + obj = open_write(output_file); + + pc = 0; + seg = 0; + pass = 1; + reset_psects(); + include(input_file); + + pc = 0; + seg = 0; + pass = 2; + reset_psects(); + include(input_file); + + psect_summary(); + dump_symtab(); + fclose(obj); + printf("errors=%d\n", error); + printf("warnings=%d\n", warning); + return error ? 1 : 0; +} + +struct inc inc[MAX_NEST]; +int inc_p = 0; +FILE *yyin; + +include(file) +char *file; +{ + FILE *fp = open_read(file); + + inc_p++; + if(inc_p >= MAX_NEST) + fatal("%s: include nesting too deep\n", file); + + inc[inc_p].file = file; + inc[inc_p].fp = fp; + inc[inc_p].line = 1; + + list_on_next = TRUE; + if(inc_p > 1 && NOT list_includes) + list_on_next = FALSE; + + yyin = inc[inc_p].fp; + if(inc_p == 1) +#ifdef FLEX + { + static int started = 0; + if(started) + yyrestart(yyin); + else + started = 1; + yyparse(); + } +#else + yyparse(); +#endif +} + +yywrap() +{ + fclose(inc[inc_p].fp); + inc_p--; + list_on = list_on_next = TRUE; + if(inc_p > 1) + list_on = list_on_next = FALSE; + if(inc_p) { + yyin = inc[inc_p].fp; + return 0; + } else { + return 1; + } +} + +struct n +sym_ref(sym) /* return symbol value or UNDEF if not defined yet */ +char *sym; +{ + struct sym *sp, *find_sym(); + struct n result; + + result.type = UNDEF; + + sp = find_sym(sym); + if(NOT sp) { + if(pass == 2) { + yyerror("%s: undefined symbol", sym); + } + return result; + } + + return sp->n; +} + +#define HASHSIZE 128 + +#define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE) + +struct sym *symtab[HASHSIZE]; + +sym_def(sym, type, seg, i, f) +char *sym; +int type; +int seg; +int i; +double f; +{ + struct sym *sp, **stop, *find_sym(); + + if(pass == 1) { + if(find_sym(sym)) { + pass = 2; /* what a kludge */ + yyerror("%s: multiply defined symbol", sym); + pass = 1; + return 1; + } + stop = &symtab[HASH(sym)]; + sp = NEW(struct sym); + sp->next = *stop; + *stop = sp; + sp->name = strsave(sym); + sp->n.type = type; + sp->n.seg = seg; + if(type == INT) + sp->n.val.i = i & 0xFFFFFF; + else + sp->n.val.f = f; + } else { + sp = find_sym(sym); + if(NOT sp) + fatal("internal error 304\n"); + if(sp->n.type != type || + type == INT && sp->n.val.i != (i & 0xFFFFFF) || + type == FLT && sp->n.val.f != f) + yyerror("%s: assembler phase error", sym); + } +} + +struct sym *find_sym(sym) +char *sym; +{ + struct sym *sp, **stop; + + stop = &symtab[HASH(sym)]; + for(sp = *stop; sp; sp = sp->next) + if(strcmp(sp->name, sym) == 0) + return sp; + + return NULL; +} + +extern char segs[]; +dump_symtab() +{ + struct sym *sp, **stop; + int i; + + printf("\n\ +Symbol Table\n\ +-------------------------------------\n"); +/* +SSSSSSSSSSSSSSSS S XXXXXX +SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD +*/ + + for(i = 0, stop = symtab; i < HASHSIZE; i++, stop++) { + for(sp = *stop; sp; sp = sp->next) { + if(sp->n.type == INT) { + printf("%16s %c %06X\n", sp->name, segs[sp->n.seg], sp->n.val.i); + fprintf(obj, "I %06X %s\n", sp->n.val.i, sp->name); + } else { + printf("%16s %c %.10f\n", sp->name, segs[sp->n.seg], sp->n.val.f); + fprintf(obj, "F %.10f %s\n", sp->n.val.f, sp->name); + } + } + } +} + +char *printcode(word) +int word; +{ + static char list[MAX], *lp; + int i; + + word &= 0xFFFFFF; + + if(binary_listing) { + sprintf(list, "%06X<", word); + for(i = 0, lp = &list[7]; i < 24; i++, lp++) { + *lp = word & 1 << 23 - i ? '1' : '0'; + if(i && i % 4 == 3) + *++lp = i % 8 == 7 ? ' ' : ','; + } + lp[-1] = '>'; + lp[0] = '\0'; + } else { + sprintf(list, "%06X", word); + } + return list; +} + +char *spacespace[2] = { +/*P:XXXX_XXXXXX_*/ + " ", +/*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/ + " "}; +char *spaces(n) +int n; +{ + return spacespace[binary_listing ? 1 : 0] + n; +} + +extern char segs[]; + +gencode(seg, pc, word) +int seg, pc, word; +{ + fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF); +} + +char fixbuf[1024]; + +char *fixstring(s) +char *s; +{ + char *bp = fixbuf; + int ival; + + while(*s) { + switch (*s) { + case '\'': + case '\"': + s++; + break; + case '\\': + switch (*++s) { + case 'b': *bp++ = '\b'; break; + case 'r': *bp++ = '\r'; break; + case 'f': *bp++ = '\f'; break; + case 'n': *bp++ = '\n'; break; + case 't': *bp++ = '\t'; break; + case '\\': *bp++ = '\\'; break; + case '0': + ival = 0; + while(*s >= '0' && *s <= '9') { + ival <<= 3; + ival += *s++ - '0'; + } + *bp++ = ival; + break; + } + break; + default: + *bp++ = *s++; + break; + } + } + *bp = '\0'; + return fixbuf; +} + +#define ONE 0x4000000 + +makefrac(s) +char *s; +{ + int frac = 0, div = 1; + int scale = 1; + + while(*s) { + switch(*s) { + case '-': + scale = -1; + break; + case '.': + div = 10; + break; + default: + frac += (*s - '0') * scale * ONE / div; + div *= 10; + break; + } + s++; + } + + return frac + scale * 4 >> 3 & 0xFFFFFF; +} + +/***************** psect stuff ************************/ + +struct psect *ptop = NULL, *cur_psect = NULL; + +reset_psects() +{ + struct psect *pp; + + for(pp = ptop; pp; pp = pp->next) { + pp->pc = pp->bottom; + } + + set_psect(NULL); +} + +psect_summary() +{ + printf("\nSummary of psect usage\n\n"); + + printf("\ + section seg base last top used avail total\n\ +-------------------------------------------------------------------------\n"); +/* +SSSSSSSSSSSSSSSSSSSSSSSS X FFFF FFFF FFFF 99999 100% 99999 100% 99999 +*/ + + summarize(ptop); /* do it recursively to place back in order */ + printf("\n"); +} + +summarize(pp) +struct psect *pp; +{ + int used, avail, of; + + if(pp == NULL) + return 1; + + used = pp->pc - pp->bottom; + avail = pp->top - pp->pc; + of = pp->top - pp->bottom; + + summarize(pp->next); + + printf("%24.24s %c %04X %04X %04X %5d %3d%% %5d %3d%% %5d\n", + pp->name, segs[pp->seg], pp->bottom, pp->pc, pp->top, + used, of ? used * 100 / of : 0, avail, of ? avail * 100 / of : 0, + of); +} + +struct psect *find_psect(name) +char *name; +{ + struct psect *pp; + + for(pp = ptop; pp; pp = pp->next) + if(strcmp(pp->name, name) == 0) + return pp; + + return NULL; +} + +set_psect(pp) +struct psect *pp; +{ + cur_psect = pp; +} + +check_psect(seg, pc) +int seg; +unsigned int pc; +{ + if(cur_psect) { + if(seg == cur_psect->seg && pc >= cur_psect->bottom && + pc <= cur_psect->top) { + cur_psect->pc = pc; + return TRUE; + } else { + return FALSE; + } + } else { + return TRUE; + } +} + +struct psect *new_psect(name, seg, bottom, top) +char *name; +int seg; +unsigned int bottom, top; +{ + struct psect *pp = find_psect(name); + + if(NOT pp) { + pp = (struct psect *)alloc(sizeof *pp); + pp->next = ptop; + ptop = pp; + pp->name = strsave(name); + pp->seg = seg; + pp->pc = bottom; + } + pp->bottom = bottom; + pp->top = top; + + return pp; +}