home *** CD-ROM | disk | FTP | other *** search
- /*
- as68k.c
-
- MC68000 Cross-Assembler
-
- Version 2.1 First Pass at clean-up by Steve Sampson
- Version 2.0 Converted to C by Ken Presser
- Version 1.0 Fortran program by Allen Kossow
-
- REFERENCE:
- Fortran version Printed in Oct, Nov 1982 Dr. Dobbs Journal
-
- NOTES:
- Symbols are unique to 8 characters
- Motorola S-Record Format (3-Byte Address) for Object File.
-
- EXCEPTIONS:
- 1) No Macros.
- 2) No PC relative addressing (except Branches).
- 3) Doesn't handle Address Registers as special cases
- (i.e. MOVEA is just a MOVE).
-
- This version is for Software Toolworks C/80 Version 3.0
- */
-
- #define MAIN
-
- #include "a:printf.h" /* C/80 Specific */
- #include "a:stdio.h" /* Standard I/O Defines */
- #include "as.h" /* Globals and Defines */
-
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- unsigned ah, al, cksum;
- int i, printer, ext;
- char exten[5], *s;
-
- /* initalize the command line switches */
- no_list = no_object = no_symbol = printer = ext = FALSE;
-
- while (--argc > 0 && argv[1][0] == '-') {
- ++argv;
- for (s = argv[0]+1; *s != '\0'; s++) {
- switch(toupper(*s)) {
- case 'L':
- no_list = TRUE;
- break;
- case 'O':
- no_object = TRUE;
- break;
- case 'S':
- no_symbol = TRUE;
- break;
- case 'P':
- strcpy(lstnam,"LST:");
- listdev = printer = TRUE;
- no_list = FALSE;
- }
- }
- }
-
- if (argc != 1) {
- fprintf(stderr,"Usage: as68k [-losp] file\n");
- exit();
- }
-
- strcpy(srcnam,*++argv);
-
- for (s = *argv, i = 0; *s != '\0'; s++, i++) {
- if (*s == '.') {
- strcpy(exten,s);
- ext = TRUE;
- srcnam[i] = argv[0][i] = '\0';
- break;
- }
- }
-
- if (!ext)
- strcat(srcnam,".S");
- else
- strcat(srcnam,exten);
-
- if ( !printer && !no_list ) {
- strcpy(lstnam,*argv);
- strcat(lstnam,".PRN");
- }
-
- if (!no_object) {
- strcpy(objnam,*argv);
- strcat(objnam,".OBJ");
- }
-
- if (!no_symbol) {
- strcpy(symnam,*argv);
- strcat(symnam,".SYM");
- }
-
- if (((symadr = alloc(MAXSYM * 4)) == ERR) ||
- ((symlin = alloc(MAXSYM * 2)) == ERR) ||
- ((symflg = alloc(MAXSM1)) == ERR) ||
- ((symsym = alloc(MAXSYM * 2)) == ERR)) {
- printf("Not enough memory for symbol table\n");
- printf("Re-compile using smaller table\n");
- exit();
- }
-
-
- /* open files */
-
- if ((sunit = fopen(srcnam,"r")) == NULL) {
- fprintf(stderr,"Unable to open %s",srcnam);
- exit();
- }
-
- if (!no_list)
- if ((lunit = fopen(lstnam,"w")) == NULL) {
- fprintf(stderr,"Unable to open %s\n",lstnam);
- no_list = TRUE;
- }
-
- if (!no_object) {
- if ((ounit = fopen(objnam,"w")) == NULL) {
- fprintf(stderr,"Unable to open %s\n",objnam);
- no_object = TRUE;
- }
- else
- fprintf(ounit,"S00600004844521B\n");
- }
-
- if (!no_symbol)
- if ((munit = fopen(symnam,"w")) == NULL) {
- fprintf(stderr,"Unable to open %s\n",symnam);
- no_symbol = TRUE;
- }
-
- /* do pass 1 */
-
- nosym = nocard = nopage = 0;
- pass = rflg = 1;
- pc = endval = 0l;
- name[0] = EOS;
-
- while (1) {
- newpc = 0l;
- source(1); /* read one line of source file */
-
- if (iserr == TRUE) /* if EOF detected do pass 2 */
- break;
-
- meflg = 0; /* reset multiple error flag */
- parse(); /* parse source line */
-
- if (prflg == 0) /* if NULL line get next line */
- continue;
-
- prcess(); /* process source line */
-
- if (iserr == TRUE) /* if end detected do pass 2 */
- break;
-
- pc += newpc;
- }
-
- /* do pass 2 */
-
- source(2); /* rewind source, reset PC */
- iercnt = endflg = hexwc = 0; /* initialize object buffer */
- pc = hexpc = oldpc = 0l;
- pass = 2;
-
- if (!no_list)
- newpag();
-
- while (1) {
- newpc = 0l;
- objwc = 0;
- source(1); /* read one line of source file */
-
- if (iserr == TRUE) /* EOF detected */
- break;
-
- meflg = 0; /* reset multiple error flag */
- parse(); /* parse line */
-
- if (!cmtflg) {
- if (prflg == 0) /* check for parsing errors */
- continue;
- prcess(); /* process it */
-
- }
-
- if (!no_list)
- lstlne(); /* generate listing */
-
- /* check if there is object code to generate */
-
- if (!no_object && objwc)
- bldobj();
-
- if (iserr == TRUE) /* do next line if not end */
- break;
-
- pc += newpc;
- }
-
- /* end of assembly, output balance of object buffer */
-
- endflg = TRUE;
- if (!no_object) {
- bldobj();
- ah = (unsigned)((endval >> 16) & (long)0x00ff);
- al = (unsigned)(endval & (long)0xffff);
- cksum = 4 + ah + ((al >> 8) & 0xff) + (al & 0xff);
- fprintf(ounit,"S804%02x%04x%02x\n",ah,al,(~cksum)&0xff);
- }
-
- /* print symbol table and error report */
-
- pst();
-
- /* close files */
-
- fclose(sunit);
-
- if (!no_list)
- fclose(lunit);
- if (!no_object)
- fclose(ounit);
- if (!no_symbol)
- fclose(munit);
- }
-
-
- source(icode)
- int icode;
- {
-
- /*
- icode = 1 => read one line from source file into srclne and lpline,
- trailing blanks are deleted. Zero Character
- is inserted at the end of the line.
- 2 => rewind source file.
-
- lpline = line printer line
- srclne = source line
- lnelen = length of source line
- iserr = TRUE if EOF on read, FALSE otherwise
- nocard = card number read from source
- */
- int i;
-
- switch (icode) {
- case 1: /* read source line */
- iserr = FALSE;
- if (newline(sunit) == NULL) {
- iserr = TRUE;
- return;
- }
- ++nocard;
-
- /* copy listing line into parsing line */
-
- for (i = 0; i < lnelen; ++i)
- srclne[i] = lpline[i];
-
- /* convert all characters */
-
- for (i = 0; i < lnelen; ++i) {
- if (srclne[i] == '\'')
- while (srclne[++i] != '\'')
- ;
- if (srclne[i] == '\t' ||
- (srclne[i] >= 32 && srclne[i] < 96))
- continue;
- else if (srclne[i] < 32)
- srclne[i] = 32;
- else
- srclne[i] -= 32;
- }
-
- /* remove trailing blanks */
-
- if (lnelen)
- while (srclne[--lnelen] == ' ')
- if (!lnelen)
- break;
-
- srclne[++lnelen] = EOS;
- return;
-
- case 2: /* rewind source file */
- fclose(sunit);
- if ((sunit = fopen(srcnam,"r")) == NULL) {
- fprintf(stderr,"Unable to re-open %s",srcnam);
- exit();
- }
- nocard = 0;
- return;
- }
- }
-
-
- newline(fd)
- FILE fd;
- {
- char *cp;
- int c;
-
- lnelen = 0;
- cp = lpline;
- while ((c = getc(fd)) != EOF && c != '\n') {
- *cp++ = c;
- if (++lnelen == 80)
- while ((c = getc(fd)) != EOF && c != '\n')
- ;
- }
-
- *cp = EOS;
-
- if (cp == lpline && c == EOF)
- return NULL;
- else
- return lpline;
- }
-
-
- symtbl(scode,iaddr,symstr)
- int scode;
- long iaddr;
- char *symstr;
- {
-
- /*
- scode = 1 => find operand in symbol table.
- if not found it is entered as
- referenced but not defined.
- the index in the table is returned in 'stind'.
- 2 => find label in symbol table.
- if found and already defined and first pass,
- the multiple defined bit is set in 'symflg'.
- if found but only previously referenced,
- the defined but previously referenced bit is set,
- and the referenced bit is cleared.
- if not found it is entered and the defined bit is set.
- iaddr = address of symbol for entering into symbol table.
- symbol= symbol to look up or enter in symbol table.
- stind = index into symbol table for symbol.
-
- FORMAT: BIT MEANING IF SET
- 0 referenced but not defined.
- 1 defined and referenced before definition.
- 2 defined and no previous reference.
- 3 multiple defined.
- 4 equated value.
- */
- char *sptr;
- int i,found,movflg,itemp;
-
- /* search for symbol in symbol table */
-
- found = movflg = FALSE;
- for (stind = 0; stind < nosym; ++stind) {
- if ((i = strcmp(symsym[stind],symstr)) < 0)
- continue;
- else if (i == 0) {
- found = TRUE;
- break;
- }
- else {
- movflg = TRUE;
- break;
- }
- }
-
- if (!found) {
-
- /* symbol was not found */
-
- if (nosym >= MAXSYM) {
- error(221);
- stind = MAXSYM;
- return stind;
- }
-
- if (movflg) {
- for (itemp = nosym; itemp > stind; --itemp) {
- symsym[itemp]=symsym[itemp-1];
- symadr[itemp]=symadr[itemp-1];
- symflg[itemp]=symflg[itemp-1];
- symlin[itemp]=symlin[itemp-1];
- }
- }
-
- ++nosym;
- if ((symsym[stind] = alloc(SYMSZ1)) == ERR) {
- fprintf(stderr,"Symbol Table Overflow\n");
- exit();
- }
-
- sptr = symsym[stind];
- for (i = 0; i < SYMSZ1; ++i)
- *sptr++ = *symstr++;
-
- if (scode != 1) {
- symflg[stind] = 4;
- symadr[stind] = iaddr;
- symlin[stind] = nocard;
- }
- else {
- symadr[stind] = 0;
- symflg[stind] = 1;
- symlin[stind] = 0;
- }
-
- return stind;
- }
- else {
-
- /* symbol found */
-
- if (pass == 2 || scode == 1)
- return stind;
-
- if (symflg[stind] == 1) {
- symflg[stind] = 2;
- symadr[stind] = iaddr;
- symlin[stind] = nocard;
- return stind;
- }
-
- symflg[stind] |= 8;
- return stind;
- }
- }
-
-
- pst()
- {
- int i,idx,ipt,iftmp;
- unsigned ah,al;
-
- if (nosym == 0)
- return;
-
- if (!no_symbol)
- wst();
-
- if (no_list) {
- sumitup();
- return;
- }
-
- newpag(); /* goto top of page */
-
- /* generate the symbol list a line at a time */
-
- for (i = 0; i < nosym; i += 3) {
- fprintf(lunit,"\n ");
- for(idx = 0; idx < 3; ++idx) {
- if (i + idx < nosym) {
- fprintf(lunit,"%s",symsym[i+idx]);
-
- ipt = strlen(symsym[i+idx]);
- while (++ipt < 9)
- putc(' ',lunit);
-
- ah = (unsigned)((symadr[i+idx] >> 16) & 0xffff);
- al = (unsigned)(symadr[i+idx] & 0xffff);
- fprintf(lunit," %04x%04x",ah,al);
-
- iftmp = symflg[i+idx];
- if (iftmp & 0x10)
- fprintf(lunit," EQ ");
- else if (iftmp & 0x08)
- fprintf(lunit," MU ");
- else if (iftmp & 0x01)
- fprintf(lunit," UN ");
- else if ((iftmp & 0x19) == 0)
- fprintf(lunit," ");
- else
- fprintf(lunit," %02x ",iftmp);
- }
- }
-
- if (--noline == 0)
- newpag();
- }
- sumitup();
- }
-
-
- sumitup()
- {
- if (pass == 2) {
- if (!no_list)
- fprintf(lunit,"\n\n %d Symbols, %d Errors detected\n",
- nosym,iercnt);
- printf("\n%d Symbols, %d Errors detected\n",nosym,iercnt);
- }
- }
-
-
- wst()
- {
- unsigned i,ah,al;
-
- for (i = 0; i < nosym; ++i) {
- ah = (unsigned)((symadr[i] >> 16) & (long)0xffff);
- al = (unsigned)(symadr[i] & (long)0xffff);
- fprintf(munit,"%s,%04x%04x,%02x\n",symsym[i],ah,al,symflg[i]);
- }
- }
-
-
- newpag()
- {
- fprintf(lunit,"\n\n\f%s\t\tMC68000 Cross-Assembler 2.1\t\tPage %d\n",
- name,++nopage);
- noline = 58;
- }
-
-
- error(ierr)
- int ierr;
- {
- int i, j, k;
- char s[80];
-
- /* errors are ignored on first pass */
-
- if (pass == 1)
- return;
-
- switch (ierr) {
- case 202: strcpy(s,"Invalid char for label start");
- break;
- case 204: strcpy(s,"Reserved word");
- break;
- case 205: strcpy(s,"Label too long");
- break;
- case 206: strcpy(s,"Parsing error");
- break;
- case 207: strcpy(s,"Invalid mode");
- break;
- case 221: strcpy(s,"Symbol table overflow");
- break;
- case 400: strcpy(s,"Undefined Opcode");
- break;
- case 401: strcpy(s,"Operand missing");
- break;
- case 402: strcpy(s,"Label missing or required");
- break;
- case 403: strcpy(s,"DC, DS or ORG operand error");
- break;
- case 404: strcpy(s,"Range error");
- break;
- case 405: strcpy(s,"Too many operands");
- break;
- case 406: strcpy(s,"Syntax error");
- break;
- case 407: strcpy(s,"Undefined symbol");
- break;
- case 408: strcpy(s,"Index size error");
- break;
- case 409: strcpy(s,"Multiply defined symbol");
- break;
- default: s[0] = EOS;
- break;
- }
-
- prflg = 3;
-
- /* require two lines remaining to print error */
-
- if (!no_list && noline < 2)
- newpag();
-
- /* if this is not the first error then don't print the line */
-
- if (!meflg) {
- if (!no_list)
- fprintf(lunit,"\n%5d ",
- nocard);
-
- for (i = 41,j = 0; i < 132; ++j) {
- if (!lpline[j])
- break;
-
- if (!no_list) {
- if (lpline[j] == '\t') {
- if (listdev) {
- k = ((i | 7) + 1) - i;
- while (k--)
- putc(' ',lunit);
- }
- else
- putc('\t',lunit);
-
- i = (i | 7) + 1;
- }
- else {
- putc(lpline[j],lunit);
- ++i;
- }
- }
-
- }
- --noline;
- }
-
- if (s[0]) {
- if (!no_list)
- fprintf(lunit,"\n+++++ ERROR %s",s);
-
- for (i = strlen(s); i < 27; ++i)
- if (!no_list)
- putc(' ',lunit);
- }
- else {
- if (!no_list)
- fprintf(lunit,"\n+++++ ERROR %3d ",
- ierr);
- }
-
- for (i = 41,j = 0; j < scanpt; ++j) {
- if (lpline[j] == '\t') {
- if (listdev)
- k = ((i | 7) + 1) - i;
-
- i = (i | 7) + 1;
- }
- else
- ++i;
-
- if (i >= 132) {
- if (!no_list)
- putc('>',lunit);
-
- break;
- }
-
- if (lpline[j] == '\t') {
- if (!no_list) {
- if (listdev)
- while (k--)
- putc(' ',lunit);
- else
- putc('\t',lunit);
- }
- }
- else if (!no_list)
- putc(' ',lunit);
- }
-
- if (i < 132)
- if (!no_list)
- putc('^',lunit);
-
- --noline;
- ++iercnt;
- meflg = 1;
- }
-
-
- lstlne()
- {
-
- /*
- Build line (or lines if DC.B DC.W DC.L) for display
-
- prflg = 0 errors detected (print line as read)
- 1 no errors detected (print normally)
- 2 DC.W / DC.L directives
- 3 suppress printout of line
- 4 DC.B directive
- 5 NAM / END / MON directives
- 6 EQU / SET directives
- 7 ORG / RORG directives
- 8 DS directive
- 9 PAGE directive
- */
-
- int i, lswrds;
- unsigned ah, al;
-
- if (pass == 1 || no_list)
- return;
-
- /* only print 5 words of an instruction */
-
- if (objwc > 5)
- lswrds = 5;
- else
- lswrds = objwc;
-
- /* check if we have to go to next page */
-
- if (!noline)
- newpag();
-
- /* check for a comment line */
-
- if (lpline[0] == '*')
- prflg = 5;
-
- switch (prflg) {
- case 0: /* errors */
- case 1: /* normal */
- case 2: /* DC.W,DC.L */
- case 7: /* ORG,RORG */
- case 8: /* DS */
- case 4: /* DC.B */
- ah = (unsigned)((pc >> 16) & (long)0xffff);
- al = (unsigned)(pc & (long)0xffff);
-
- fprintf(lunit,"\n%5d %02x%04x ",nocard,ah,al);
-
- for (i = 1; i <= 5; ++i) {
- if (i <= lswrds)
- fprintf(lunit,"%04x ",objbuf[i]);
- else
- fprintf(lunit," ");
- }
- lst1();
- break;
-
- case 5: /* NAM,END,MON and Remarks */
- fprintf(lunit,"\n%5d ",
- nocard);
- lst1();
- break;
-
- case 6: /* EQU,SET */
- fprintf(lunit,"\n%5d = %4x%04x ",
- nocard,opnwrd[3],opnwrd[2]);
- lst1();
- break;
-
- case 9: /* page */
- newpag();
-
- case 3: /* suppress print */
- return;
- }
- --noline;
- }
-
-
- lst1()
- {
- int i, j, k;
-
- for (i = 41,j = 0; lpline[j]; ++j) {
- if (lpline[j] == '\t') {
- if (listdev)
- k = ((i | 7) + 1) - i;
- i = (i | 7) + 1;
- }
- else
- ++i;
-
- if (i >= 132)
- break;
-
- if (listdev && lpline[j] == '\t')
- while (k--)
- putc(' ',lunit);
- else
- putc(lpline[j],lunit);
- }
- }
-
-
- bldobj()
- {
- int i;
- long newval;
-
- /* check for the end of assembly flag */
- /* if set, output the balance of the object buffer */
-
- if (endflg) {
- if (hexwc)
- wrtobj();
- return;
- }
-
- /* check the PC value with that of the one saved */
- /* if the two are not equal then output the balance */
- /* of the object buffer and start at the new PC value */
-
- if (pc != oldpc) {
- if (hexwc)
- wrtobj();
-
- hexpc = oldpc = pc;
- }
-
- /* transfer object buffer to internal buffer. */
- /* If the internal buffer is full then output it. */
-
- for (i = 1; i <= objwc; ++i) {
- hexbuf[++hexwc] = objbuf[i];
- if (hexwc >= 8) {
-
- /* output buffer is full */
-
- wrtobj();
-
- /* calculate new PC for internal buffer */
-
- newval = (long)i * 2;
- hexpc = pc + newval;
- }
- }
-
- /* calculate new PC by adding object word count to current PC */
-
- oldpc += newpc;
- }
-
-
- wrtobj()
- {
-
- /*
- Output the contents of the Object buffer
-
- hexpc = starting PC for buffer
- hexwc = number of words used in buffer
- hexbuf= 8 word Object buffer
- */
- int i;
- unsigned ah,al,cksum;
-
- ah = (unsigned)((hexpc >> 16) & (long)0xff);
- al = (unsigned)(hexpc & (long)0xffff);
- fprintf(ounit,"S2%02x%02x%04x",hexwc*2+4,ah,al);
- cksum=((hexwc * 2 + 4) & 0xff) + ah + ((al >> 8) & 0xff) + (al & 0xff);
-
- for (i = 1; i <= hexwc; ++i) {
- fprintf(ounit,"%04x",hexbuf[i]);
- cksum += ((hexbuf[i] >> 8) & 0xff) + (hexbuf[i] & 0xff);
- }
-
- fprintf(ounit,"%02x\n",(~cksum) & 0xff);
- hexwc = 0;
- }
-
-
- long
- asn(wrd2,wrd3)
- unsigned wrd2,wrd3;
- {
- return ( ((wrd3 << 16) & 0xffff0000) | (wrd2 & (long)0x0ffff) );
- }