URL
https://opencores.org/ocsvn/tms1000/tms1000/trunk
Subversion Repositories tms1000
[/] [tms1000/] [trunk/] [assembler/] [casm.c] - Rev 5
Go to most recent revision | Compare with Previous | Blame | View Log
/* casm.c CASM is an assembler for the tms1000 processor. */ #include <stdarg.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include "symtab.h" #include "casm.h" char *progname; int pass; int lineno; int errors; int warnings; int group; /* current rom group */ int rom; /* current rom */ int pc; /* current pc */ int dsr; /* delayed select rom */ int dsg; /* delayed select group */ char flag_char; int objflag; /* used to remember args to emit() */ int objcode; int symtab_flag; int last_instruction_type; int targflag; /* used to remember args to target() */ int targgroup; int targrom; int targpc; char linebuf [MAX_LINE]; char *lineptr; #define MAX_ERRBUF 2048 char errbuf [MAX_ERRBUF]; char *errptr; #define SRC_TAB 32 char listbuf [MAX_LINE]; char *listptr; #ifndef PATH_MAX #define PATH_MAX 256 #endif char srcfn [PATH_MAX]; char objfn [PATH_MAX]; char listfn [PATH_MAX]; FILE *srcfile = NULL; FILE *objfile = NULL; FILE *listfile = NULL; t_symtab symtab /*[MAXGROUP] [MAXROM]*/; /* separate symbol tables for each ROM */ void format_listing (void) { int i; sprintf (listptr, "%4d ", lineno); listptr += strlen (listptr); if (objflag) { sprintf (listptr, "L%03x: ", (rom << 6)+pc); listptr += strlen (listptr); for (i = 0x80; i; i >>= 1) *listptr++ = (objcode & i) ? '1' : '.'; *listptr = '\0'; } else { strcat (listptr, " "); listptr += strlen (listptr); } if (targflag) { sprintf (listptr, " -> L%1o%1o%03o", targgroup, targrom, targpc); listptr += strlen (listptr); } else { strcat (listptr, " "); listptr += strlen (listptr); } sprintf (listptr, " %c%c%c%c%c ", flag_char, flag_char, flag_char, flag_char, flag_char); listptr += strlen (listptr); strcat (listptr, linebuf); listptr += strlen (listptr); } void do_pass (int p) { int i; pass = p; lineno = 0; errors = 0; warnings = 0; pc = 0; dsr = rom; dsg = group; last_instruction_type = OTHER_INST; printf ("Pass %d rom", pass); while (fgets (linebuf, MAX_LINE, srcfile)) { /* remove newline */ i = strlen (linebuf); if (linebuf [i - 1] == '\n') linebuf [i - 1] = '\0'; lineno++; lineptr = & linebuf [0]; listptr = & listbuf [0]; listbuf [0] = '\0'; errptr = & errbuf [0]; errbuf [0] = '\0'; objflag = 0; targflag = 0; flag_char = ' '; symtab_flag = 0; yyparse (); if (pass == 2) { if (symtab_flag) print_symbol_table (symtab, listfile); else { format_listing (); fprintf (listfile, "%s\n", listbuf); if (errptr != & errbuf [0]) { fprintf (stderr, "%s\n", listbuf); fprintf (listfile, "%s", errbuf); fprintf (stderr, "%s", errbuf); } } } if (objflag) { pc = ((pc != 31) && ((pc >> 4) != 0) && (((pc & 0xf) == 15) || ((pc >> 4) != 3))) ? (pc << 1) : (pc << 1)+1; pc = pc & 0x3f; } //pc = (pc + 1) & 0xff; } printf ("\n"); } void munge_filename (char *dst, char *src, char *ext) { int i; int lastdot = 0; for (i = 0; src [i]; i++) { if (src [i] == '.') lastdot = i; } if (lastdot == 0) lastdot = strlen (src); memcpy (dst, src, lastdot); dst [lastdot] = '\0'; strcat (dst, ext); } int main (int argc, char *argv[]) { progname = argv [0]; if (argc != 2) { fprintf (stderr, "Usage: %s sourcefile\n", progname); exit (1); } symtab = alloc_symbol_table (); if (! symtab ) fatal ("symbol table allocation failed\n"); strcpy (srcfn, argv [1]); srcfile = fopen (srcfn, "r"); if (! srcfile) fatal ("can't open input file '%s'\n", srcfn); munge_filename (objfn, srcfn, ".mem"); munge_filename (listfn, srcfn, ".lst"); objfile = fopen (objfn, "w"); if (! objfile) fatal ("can't open input file '%s'\n", objfn); listfile = fopen (listfn, "w"); if (! listfile) fatal ("can't open listing file '%s'\n", listfn); rom = 0; group = 0; do_pass (1); rewind (srcfile); do_pass (2); err_printf ("%d errors, %d warnings\n", errors, warnings); fclose (srcfile); fclose (objfile); fclose (listfile); } void yyerror (char *s) { error ("%s\n", s); } void do_label (char *s) { int prev_val; if (pass == 1) { if (! create_symbol (symtab, s, (rom << 6) + pc, lineno)) error ("multiply defined symbol '%s'\n", s); } else if (! lookup_symbol (symtab, s, & prev_val)) error ("undefined symbol '%s'\n", s); else if (prev_val != ((rom << 6) + pc)) error ("phase error for symbol '%s'\n", s); } static void emit_core (int op, int inst_type) { objcode = op; objflag = 1; last_instruction_type = inst_type; if ((pass == 2) && objfile) fprintf (objfile, "@%03x %02x\n", (rom<<6)+pc, op); } void emit (int op) { emit_core (op, OTHER_INST); } void emit_arith (int op) { emit_core (op, ARITH_INST); } void emit_test (int op) { emit_core (op, TEST_INST); } void target (int g, int r, int p) { targflag = 1; targgroup = g; targrom = r; targpc = p; } int range (int val, int min, int max) { if ((val < min) || (val > max)) { error ("value out of range [%d to %d], using %d", min, max, min); return min; } return val; } char *newstr (char *orig) { int len; char *r; len = strlen (orig); r = (char *) malloc (len + 1); if (! r) fatal ("memory allocation failed\n"); memcpy (r, orig, len + 1); return (r); } /* * print to both listing error buffer and standard error * * Use this for general messages. Don't use this for warnings or errors * generated by a particular line of the source file. Use error() or * warning() for that. */ int err_vprintf (char *format, va_list ap) { int res; if (listfile) vfprintf (listfile, format, ap); res = vfprintf (stderr, format, ap); return (res); } int err_printf (char *format, ...) { int res; va_list ap; va_start (ap, format); res = err_vprintf (format, ap); va_end (ap); return (res); } /* generate fatal error message to stderr, doesn't return */ void fatal (char *format, ...) { va_list ap; fprintf (stderr, "fatal error: "); va_start (ap, format); vfprintf (stderr, format, ap); va_end (ap); exit (2); } /* generate error or warning messages and increment appropriate counter */ /* actually just puts the message into the error buffer */ int error (char *format, ...) { int res; va_list ap; err_printf ("error in file %s line %d: ", srcfn, lineno); va_start (ap, format); res = err_vprintf (format, ap); va_end (ap); errptr += res; errors ++; return (res); } int warning (char *format, ...) { int res; va_list ap; err_printf ("warning in file %s line %d: ", srcfn, lineno); va_start (ap, format); res = err_vprintf (format, ap); va_end (ap); errptr += res; warnings ++; return (res); }
Go to most recent revision | Compare with Previous | Blame | View Log