home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
042.lha
/
assembler
/
A68kmain.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-25
|
15KB
|
498 lines
/*------------------------------------------------------------------*/
/* */
/* MC68000 Cross Assembler */
/* */
/* Copyright (c) 1985 by Brian R. Anderson */
/* */
/* Main program - June 18, 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.00 - June 18, 1987";
#include <stdio.h>
#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]; /* File names */
int endfile; /* End-of-file flag */
long maxheap, maxheap2; /* Maximum heap sizes */
int cmderror, i, j, dummy;
long templong;
cmderror = FALSE; /* Clear command-line error flag */
SourceFN[0] = '\0'; /* Don't have source name 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 = 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 '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 (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, 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 (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 && !SuppList) {
if ((List = fopen (ListFN, "w")) == NULL) {
printf ("Unable to open listing file.\n");
cmderror = TRUE;
}
}
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;
}
}
if (cmderror) {
printf ("\n");
printf ("Usage: a68k <source file>\n");
printf (" [-o<object file>]\n");
printf (" [-l<listing file>]\n");
printf (" [-i<include dirlist>]\n");
printf (" [-p<page depth>]\n");
printf (" [-w[<heap size>][,<heap size>]]\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 (strlen (Label) != 0) { /* If statement is labeled, */
ReadSymTab (Label); /* check for duplicate defn. */
if (Sym->Defn != LineCount) {
AddRef (LineCount); /* Got one - flag as reference */
if (Sym->Flags & 4) {
if (Dir != Set)
Error (0, SymDup);
} else {
if (Dir == Set)
Error (0, SymDup);
}
} else {
if ((Dir != Equ) && (Dir != Set)
&& (Dir != Equr) && (Dir != Reg))
if (Sym->Val != AddrCnt)
Error (0, Phase); /* Assembler error */
}
}
if (!SuppList)
WriteListLine (List);
WriteSrecLine (Srec);
AddrCnt += AddrAdv; /* Advance location 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 (!SuppList)
WriteSymTab (List); /* List the symbol table */
/* 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 */
}