/*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Main program - September 9, 1987 */ /* */ /* This program may be copied for personal, non-commercial use */ /* only, provided that the above copyright notice is included */ /* on all copies of the source code. Copying for any other use */ /* without the consent of the author is prohibited. */ /* */ /*------------------------------------------------------------------*/ /* */ /* Originally published (in Modula-2) in */ /* Dr. Dobb's Journal, April, May, and June 1986. */ /* */ /* AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ char Version[] = "1.02 (September 9, 1987)"; #include #define PRIMARY #include "a68kdef.h" #include "a68kglb.h" /********************************************************************/ /* */ /* NOTE: the following line, plus any additional references */ /* to _fmode, is inserted to make this program work under */ /* the MS-DOS version of Lattice C. It is not necessary */ /* for the Amiga version, but does no harm if left in. */ /* */ /********************************************************************/ int _fmode = 0; /* File mode - 0x8000 for binary */ /* Functions */ extern int LineParts(), GetField(), Instructions(), ObjDir(); extern int GetSize(), GetInstModeSize(), GetMultReg(); extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl(); extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue(); #ifdef AZTEC_C extern char *lmalloc(); #else extern char *malloc(); #endif extern FILE *fopen(); main(argc,argv) int argc; char *argv[]; { char ListFN[MAXFN], SrecFN[MAXFN], EquateFN[MAXFN]; /* File names */ int MakeEqu; /* Create an equate file */ FILE *EquFile; /* Equate file pointer */ int endfile; /* End-of-file flag */ long maxheap, maxheap2; /* Maximum heap sizes */ int cmderror, dummy; long templong; register struct SymTab *sym; register int i, j; cmderror = FALSE; /* Clear command-line error flag */ SourceFN[0] = '\0'; /* Don't have source name yet */ HeaderFN[0] = EquateFN[0] = '\0'; /* No header or equate files yet */ ListFN[0] = SrecFN[0] = '\0'; /* Indicate default file names */ InclList[0] = '\0'; /* Clear the include directory list */ IdntName[0] = '\0'; /* Clear program unit name */ LnMax = 60; XrefList = DumpSym = GotEqur = MakeEqu = FALSE; SuppList = TRUE; /* Default to no listing file */ maxheap = DEFHEAP; /* Primary heap size default */ maxheap2 = DEFHEAP2; /* Secondary heap size default */ printf ("\n68000 Cross Assembler\n"); printf ("Copyright (c) 1985 by Brian R. Anderson\n\n"); printf ("AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.\n"); printf ("Version %s\n\n", Version); for (i = 1; i < argc; i++) { /* Analyze command line */ if (argv[i][0] != '-') { if (SourceFN[0] == '\0') strcpy (SourceFN, argv[i]); /* Source file name */ else if (SrecFN[0] == '\0') strcpy (SrecFN, argv[i]); /* Object file name */ else if (ListFN[0] == '\0') strcpy (ListFN, argv[i]); /* Listing file name */ else { printf ("Too many file names.\n"); cmderror = TRUE; } } else { switch (argv[i][1]) { case 'D': case 'd': DumpSym = TRUE; if (argv[i][2]) { printf ("Invalid symbol table dump switch.\n"); cmderror = TRUE; } break; case 'E': /* Equate file name */ case 'e': MakeEqu = TRUE; if (EquateFN[0]) { printf ("Equate file is declared more than once.\n"); cmderror = TRUE; } else if (argv[i][2]) strcpy (EquateFN, &argv[i][2]); break; case 'H': /* Header file name */ case 'h': if (HeaderFN[0]) { printf ("Header file is declared more than once.\n"); cmderror = TRUE; } else if (argv[i][2]) { strcpy (HeaderFN, &argv[i][2]); } else { printf ("Header file name is missing\n"); cmderror = TRUE; } break; case 'I': /* Include directories */ case 'i': if (argv[i][2]) { if (InclList[0]) strcat (InclList, ","); /* Add to previous list */ strcat (InclList, &argv[i][2]); } else { printf ("Include directory list is missing.\n"); cmderror = TRUE; } break; case 'L': /* Listing file name */ case 'l': SuppList = FALSE; /* Produce a listing */ if (ListFN[0]) { printf ("List file is declared more than once.\n"); cmderror = TRUE; } else if (argv[i][2]) strcpy (ListFN, &argv[i][2]); break; case 'O': /* Object file name */ case 'o': if (SrecFN[0]) { printf ("Object file is declared more than once.\n"); cmderror = TRUE; } else if (argv[i][2]) { strcpy (SrecFN, &argv[i][2]); } else { printf ("Object file name is missing\n"); cmderror = TRUE; } break; case 'P': case 'p': if ((LnMax = CalcValue(&argv[i][2], 0)) < 10) { printf ("Invalid page depth.\n"); cmderror = TRUE; } break; case 'S': case 's': SFormat = TRUE; if (argv[i][2]) { printf ("Invalid S-format switch.\n"); cmderror = TRUE; } break; case 'W': case 'w': if (argv[i][2] != ',') { maxheap = CalcValue(&argv[i][2], 0); if (maxheap < MAXLINE) maxheap = MAXLINE; /* Minimum heap size */ maxheap &= ~3L; /* Long-word alignment */ } for (j = 2; argv[i][j]; j++) { if (argv[i][j] == ',') { /* Find secondary size */ maxheap2 = CalcValue(&argv[i][j+1], 0); if (maxheap2 < MAXLINE) { maxheap2 = MAXLINE; } maxheap2 &= ~3L; break; } } break; case 'X': case 'x': XrefList = TRUE; SuppList = FALSE; /* We must want a listing */ if (argv[i][2]) { printf ("Invalid cross-reference switch.\n"); cmderror = TRUE; } break; default: printf ("Unrecognized switch.\n"); cmderror = TRUE; break; } } } if (SourceFN[0] == '\0') { /* Default list file name */ printf ("Source file name is missing.\n"); cmderror = TRUE; } if (EquateFN[0] == '\0') { /* Default equate file name */ strcpy (EquateFN, SourceFN); i = strlen (EquateFN); while (--i > 0) { if (EquateFN[i] == '.') { EquateFN[i] = '\0'; /* Chop off name extension */ break; } } strcat (EquateFN, ".equ"); /* Equate file name extension */ } if (ListFN[0] == '\0') { /* Default list file name */ strcpy (ListFN, SourceFN); i = strlen (ListFN); while (--i > 0) { if (ListFN[i] == '.') { ListFN[i] = '\0'; /* Chop off name extension */ break; } } strcat (ListFN, ".lst"); /* List file name extension */ } if (SrecFN[0] == '\0') { /* Default object file name */ strcpy (SrecFN, SourceFN); i = strlen (SrecFN); while (--i > 0) { if (SrecFN[i] == '.') { SrecFN[i] = '\0'; /* Chop off name extension */ break; } } if (SFormat) strcat (SrecFN, ".s"); /* S-format name extension */ else strcat (SrecFN, ".o"); /* AmigaDOS format extension */ } if (strcmp (SourceFN, EquateFN) == 0) { printf ("Source and equate file names are the same.\n"); cmderror = TRUE; } if (strcmp (SourceFN, ListFN) == 0) { printf ("Source and listing file names are the same.\n"); cmderror = TRUE; } if (strcmp (SourceFN, SrecFN) == 0) { printf ("Source and object file names are the same.\n"); cmderror = TRUE; } if (strcmp (EquateFN, ListFN) == 0) { printf ("Equate and listing file names are the same.\n"); cmderror = TRUE; } if (strcmp (EquateFN, SrecFN) == 0) { printf ("Equate and object file names are the same.\n"); cmderror = TRUE; } if (strcmp (ListFN, SrecFN) == 0) { printf ("Listing and object file names are the same.\n"); cmderror = TRUE; } /* Open Files. */ _fmode = 0x8000; /****** MS-DOS only ******/ if (!cmderror) { if ((InFile = fopen (SourceFN, "r")) == NULL) { printf ("Unable to open source file.\n"); cmderror = TRUE; } } _fmode = 0; /****** MS-DOS only ******/ if (!cmderror && MakeEqu) { if ((EquFile = fopen (EquateFN, "w")) == NULL) { printf ("Unable to open equate file.\n"); cmderror = TRUE; fclose (InFile); /* Close any opened files */ } } if (!cmderror && !SuppList) { if ((List = fopen (ListFN, "w")) == NULL) { printf ("Unable to open listing file.\n"); cmderror = TRUE; fclose (InFile); if (MakeEqu) fclose (EquFile); } } if (!SFormat) _fmode = 0x8000; /****** MS-DOS only ******/ if (!cmderror) { if ((Srec = fopen (SrecFN, "w")) == NULL ) { printf ("Unable to open object code file.\n"); cmderror = TRUE; fclose (InFile); if (MakeEqu) fclose (EquFile); if (!SuppList) fclose (List); } } if (cmderror) { printf ("\n"); printf ("Usage: a68k \n"); printf (" [-e]\n"); printf (" [-h
]\n"); printf (" [-i]\n"); printf (" [-l]\n"); printf (" [-o]\n"); printf (" [-p]\n"); printf (" [-w[][,]]\n"); printf (" [-d] [-s] [-x]\n\n"); printf ("Command-line arguments can appear in any order.\n"); printf ("Heap size default (bytes): -w"); printf ("%ld,%ld\n", (long) DEFHEAP, (long) DEFHEAP2); printf ("\n"); exit(20); } #ifdef AZTEC_C Heap = lmalloc (maxheap); #else Heap = malloc ((unsigned) maxheap); #endif if (Heap == NULL) { printf ("Unable to allocate primary heap!\n"); exit(20); } HeapLim = Heap; /* Heap limit (start out empty) */ LowHeap = (Heap + maxheap); SymStart = (struct SymTab *) (LowHeap); /* Symbol table */ #ifdef AZTEC_C Heap2 = lmalloc (maxheap2); #else Heap2 = malloc ((unsigned) maxheap2); #endif if (Heap2 == NULL) { printf ("Unable to allocate secondary heap!\n"); exit(20); } NextFNS = Heap2; InF = (struct InFCtl *) (Heap2 + maxheap2); LowInF = --InF; InFNum = OuterMac = SkipNest = InF->Pos = InF->MCnt = 0; InF->Line = 0; InF->UPtr = 0; InF->NPtr = NextFNS; InF->NArg = -1; strcpy (NextFNS, SourceFN); NextFNS += strlen (SourceFN) + 1; High2 = NextFNS; Low2 = (char *) LowInF; _fmode = 0x8000; /****** MS-DOS only ******/ printf ("\nAssembling %s\n\n\n", SourceFN); /*------------------------------------------------------------------- Begin Pass 1. */ printf ("PASS 1\n"); LineCount = LabLine = MacCount = ErrorCount = NumSyms = 0; AddrCnt = SectStart = 0L; /* Assume ORG = 0 to start */ CurrHunk = NextHunk = 0L; /* Start in hunk zero */ HunkType = HunkNone; /* We're not in a hunk yet */ HunkFlags = SectLine = 0; endfile = ListOff = Pass2 = FALSE; while (!endfile && (strcmp (OpCode, "END") != 0)) { PrevDir = Dir; /* Save previous directive */ endfile = LineParts (dummy); /* Get a statement */ Dir = ObjDir (Srec); /* Process directives */ GetObjectCode (dummy); /* Length if executable */ if ((HunkType == HunkNone) && (AddrAdv != 0)) { Sym = SymStart; /* Insert at head of table */ templong = (long) HunkCode << 16; AddSymTab (" ", 0L, templong, LineCount, 16); Sect = Sym; /* Create an unnamed section */ HunkType = HunkCode; SectLine = LineCount; NextHunk++; } if ((Label[0] != '\0') && (Dir != Set) && (Dir != Equr) && (Dir != Reg)) { if (!ReadSymTab (Label)) { /* Make a new entry */ AddSymTab (Label, AddrCnt, CurrHunk, LineCount, 0); } else if ((Sym->Flags & 1) /* If dup., ignore */ || (Sym->Defn == 0)) { /* else fill in */ Sym->Val = AddrCnt; /* Current loc. */ Sym->Hunk = CurrHunk; /* Hunk number */ Sym->Defn = LineCount; /* Statement number */ Sym->Flags &= ~1; /* Clear XREF flag */ } if (Dir == Equ) { Sym->Val = ObjSrc; /* Equated value */ Sym->Hunk = Src.Hunk; /* Hunk number */ } } AddrCnt += AddrAdv; /* Advance location counter */ } /*---------------------------------------------------------------- Begin Pass 2. */ printf ("PASS 2\n"); InF = (struct InFCtl *) (Heap2 + maxheap2); InF--; InFNum = OuterMac = SkipNest = InF->Pos = InF->MCnt = 0; InF->Line = 0; InF->UPtr = 0; InF->NPtr = Heap2; InF->NArg = -1; fclose (InFile); /* "Rewind" the source file */ InFile = fopen (SourceFN, "r"); NextFNS = Heap2 + strlen (SourceFN) + 1; Pass2 = TRUE; LineCount = LabLine = MacCount = ErrorCount = 0; AddrCnt = CurrHunk = SectStart = EndAddr = 0L; HunkType = HunkNone; HunkFlags = SectLine = 0; endfile = ListOff = FALSE; if ((Sym = SymStart) < (struct SymTab *) (Heap + maxheap)) { while (Sym->Flags & 16) { Sym->Val = 0L; /* Back to start of all sections */ Sym++; } } TTLstring[0] = '\0'; /* Clear title string */ if ((templong = (HeapLim - Heap) & 3L) != 0) HeapLim += 4 - templong; HighHeap = HeapLim; /* High-water mark in heap */ RelStart = (struct RelTab *) HeapLim; /* Relocation table */ RefStart = (struct Ref *) SymStart; /* Cross-reference table */ /* Sign on messages for listing file */ LnCnt = 999; PgCnt = 0; TTLstring[0] = '\0'; if (!SuppList) { CheckPage (List, FALSE); /* Print headings */ fprintf (List, "68000 Cross Assembler\n"); fprintf (List, "Copyright (c) 1985 by Brian R. Anderson\n\n"); fprintf (List, "AmigaDOS conversion copyright (c) 1987"); fprintf (List, " by Charlie Gibbs.\n"); fprintf (List, "Version %s\n\n", Version); LnCnt += 6; } StartSrec (Srec, IdntName); /* Write object header record */ /* Process the second pass. */ OpCode[0] = '\0'; /* Kill "END" from pass 1! */ while (!endfile && (strcmp(OpCode,"END") != 0)) { PrevDir = Dir; /* Save previous directive */ endfile = LineParts (dummy); /* Get a statement */ if (!endfile) { Dir = ObjDir (Srec); /* Process directives */ GetObjectCode (dummy); /* Executable object code */ if (Label[0] != '\0') { /* If statement is labeled, */ ReadSymTab (Label); /* check for duplicate defn. */ if (Sym->Defn != LineCount) { AddRef (LineCount); /* Got one - flag as reference */ if (Dir == Set) { if ((Sym->Flags & 4) == 0) Error (0, SymDup); /* Can't SET normal label */ } else { Error (0, SymDup); /* Ordinary duplicate */ } } else if (Dir == Set) { AddRef (LineCount); /* Flag all SETs as references */ } else { if (Sym->Val != AddrCnt) if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg)) Error (0, Phase); /* Assembler error */ } } if (!SuppList) WriteListLine (List); WriteSrecLine (Srec); AddrCnt += AddrAdv; /* Advance locaton counter */ } else { Error (0, EndErr); /* END statement is missing */ if (!SuppList) WriteListLine (List); } } /*--------------------------------------------------------------------- Clean up. */ fclose (InFile); /* Finished with source file */ EndSdata (Srec, EndAddr); /* Write remaining data and end record */ fclose (Srec); /* Finished with object file */ if (XrefList) WriteSymTab (List); /* List the symbol table */ /* Write all absolute symbols to an equate file if desired. */ if (MakeEqu) { fprintf (EquFile, "* Equate file for %s\n", SourceFN); fprintf (EquFile, "* Created by A68k version %s\n", Version); for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) { if (((sym->Hunk & 0x00007FFFL) == ABSHUNK) && ((sym->Flags == 0) || (sym->Flags == 2))) { fprintf (EquFile, "%s\tEQU\t$", sym->Nam); LongPut (EquFile, sym->Val, 4); fprintf (EquFile, "\n"); } } fclose (EquFile); } /* Write error count to console and listing file. */ printf (" \n\nEnd of assembly - "); if (!SuppList) fprintf (List, "\n\nEnd of assembly - "); if (ErrorCount == 0) { printf ("no errors were found.\n\n"); if (!SuppList) fprintf (List, "no errors were found.\n\n"); } else if (ErrorCount == 1) { printf ("1 error was found.\n\n"); if (!SuppList) fprintf (List, "1 error was found.\n\n"); } else { printf ("%d errors were found.\n\n", ErrorCount); if (!SuppList) fprintf (List, "%d errors were found.\n\n", ErrorCount); } templong = (long) (HighHeap - Heap); if (LowHeap < (char *) RefStart) templong += (long) (Heap + maxheap - LowHeap); else templong += (long) (Heap + maxheap - (char *) RefStart); printf ("Heap usage (bytes): -w%ld", templong); if (!SuppList) fprintf (List, "Heap usage (bytes): -w%ld", templong); templong = (long) (High2 - Heap2); if (Low2 < (char *) LowInF) templong += (long) (Heap2 + maxheap2 - Low2); else templong += (long) (Heap2 + maxheap2 - (char *) LowInF); printf (",%ld\n\n", templong); if (!SuppList) { fprintf (List, ",%ld\n\f", templong); /* One last page eject */ fclose (List); /* Finished with listing file */ } free (Heap); /* Release heap space */ free (Heap2); exit (ErrorCount ? 10 : 0); /* All done */ }