home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d110
/
a68k.lha
/
A68k
/
A68kmisc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-10-28
|
21KB
|
739 lines
/*------------------------------------------------------------------*/
/* */
/* MC68000 Cross Assembler */
/* */
/* Copyright (c) 1985 by Brian R. Anderson */
/* */
/* Miscellaneous routines - September 8, 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. */
/* */
/*------------------------------------------------------------------*/
#include <stdio.h>
#include "a68kdef.h"
#include "a68kglb.h"
char Sdata[MAXSREC]; /* S-record data */
int Sindex; /* Index for Sdata */
int NumRExt, NumR32, NumR16, NumR8;
static char *errmsg[] = {
"--- Unknown error code ---",
"Identifier too long -- Truncated!",
"No such op-code.",
"Duplicate Symbol.",
"Undefined Symbol.",
"Addressing mode not allowed here.",
"Error in operand format.",
"Error in relative branch.",
"Address mode error.",
"Operand size error.",
"END statement is missing.",
"Value must be absolute.",
"Relocatability error.",
"Too many nested INCLUDEs.",
"INCLUDE file cannot be opened.",
"Illegal forward reference.",
"Not supported in S-format.",
"This instruction needs a label.",
"Pass 1 / Pass 2 phase error.",
"ENDM statement is missing.",
"Too much DC data.",
"Too many SECTIONs.",
"Section may not be unnamed.",
"Wrong type in continuation.",
"Duplicate macro definition.",
""};
/* Functions */
extern int LineParts(), GetField(), Instructions(), ObjDir();
extern int GetSize(), GetInstModeSize(), GetMultReg();
extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
extern long GetValue(), CalcValue();
extern char *malloc();
extern FILE *fopen();
long AddrBndW(), AddrBndL();
long AddrBndW (v) long v;
/* Advances "v" to the next word boundary */
{
if (v & 1L) {
AppendSdata (Srec, 0L, 1);
v++;
}
return (v);
}
long AddrBndL (v) long v;
/* Advances "v" to the next long-word boundary */
{
long templong;
v = AddrBndW (v); /* Bump to word boundary first */
if (v & 2L) { /* If still not aligned, */
templong = NOP; /* generate a NOP */
AppendSdata (Srec, templong, 2);
v += 2;
}
return (v);
}
WriteListLine (f) FILE *f;
/* Writes one line to the Listing file, including Object Code */
{
register int i, j;
long templong;
char macflag;
if (errlim == 0)
if ((Dir == Page) || (Dir == Space) || (Dir == Title)
|| (Dir == DoList) || (Dir == NoList) || (ListOff))
return; /* Don't print unless they have errors */
CheckPage (f, FALSE); /* Print headings if necessary */
if (PrntAddr) {
if ((Dir == Equ) || (Dir == Set))
LongPut (f, ObjSrc, 3); /* Equated value */
else
LongPut (f, AddrCnt, 3); /* Current location */
fprintf (f, " ");
} else
fprintf (f, " "); /* Don't print location */
LongPut (f, ObjOp, nO); /* Generated code */
if (nS != 0) {
fprintf (f, " ");
LongPut (f, ObjSrc, nS);
}
if (nD != 0) {
fprintf (f, " ");
LongPut (f, ObjDest, nD);
}
if ((j = nX) > 0) { /* String data */
if ((j + nO + nS + nD) > 12)
j = 12 - nO - nS - nD;
for (i = 0; i < j; i++) {
templong = ObjString[i];
LongPut (f, templong, 1);
}
}
i = 6 + (nO + nS + nD + j) * 2; /* Hex digits printed */
if (nS != 0) i++; /* Space between operands */
if (nD != 0) i++;
while (i < ObjMAX) {
fprintf (f, " ");
i++;
}
if ((InFNum == 0) || (OuterMac == 0))
macflag = ' '; /* Open code */
else if (InFNum > OuterMac)
macflag = '+'; /* Inner macro */
else if ((InFNum == OuterMac) && (Dir != MacCall))
macflag = '+'; /* Outermost macro */
else
macflag = ' '; /* We're outside macros */
fprintf (f, " %4d%c%s\n", LineCount, macflag, Line);
for (i = 0; i < errlim; i++) { /* Write error messages. */
CheckPage (f, FALSE);
fprintf (f, "%s", errmsg[errcode[i]]);
for (j=strlen(errmsg[errcode[i]]); j<ObjMAX+8+errpos[i]; j++)
fprintf (f, " ");
fprintf (f, "^ "); /* Error flag */
if (i == 0) {
if (InF->UPtr == 0)
fprintf (f, "%s", InF->NPtr); /* Module name */
else
fprintf (f, "(user macro)"); /* In a user macro */
fprintf (f, " line %d", InF->Line); /* Line number */
}
fprintf (f, "\n");
}
}
WriteSymTab (f) FILE *f;
/* Lists symbol table in alphabetical order */
{
int printhunk, i;
char *p;
register int j, k;
struct SymTab *sym;
struct Ref *ref;
LnCnt = 999; /* Skip to a new page. */
for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) {
CheckPage (f, TRUE);
p = sym->Nam; /* Pointer to symbol */
while (*p == ' ') /* Skip leading blanks, if any */
p++;
fprintf (f, "%-11s ", p); /* Symbol or macro name */
if (strlen (p) > 11) /* Long symbol - go to new line */
fprintf (f, "\n ");
printhunk = FALSE; /* Assume no hunk no. to print */
if (sym->Defn == 0)
fprintf (f, " *** UNDEFINED *** ");
else if (sym->Flags & 4)
fprintf (f, " -- SET Symbol -- ");
else if (sym->Flags & 8)
fprintf (f, " +++ MACRO +++ %4d", sym->Defn);
else if (sym->Flags & 0x10) {
fprintf (f, " SECTION ");
printhunk = TRUE;
} else if (sym->Flags & 0x20) {
fprintf (f, " %c", (sym->Val & 8) ? 'A' : 'D');
fprintf (f, "%d ", sym->Val & 7);
printhunk = TRUE;
} else {
LongPut (f, sym->Val, 4); /* Value */
fprintf (f, " ");
printhunk = TRUE;
}
if (printhunk) {
j = sym->Hunk & 0x00007FFFL; /* Hunk number */
if (sym->Flags & 0x60)
fprintf (f, " Reg"); /* Register or list */
else if (sym->Hunk & 0x00008000L)
fprintf (f, " Ext"); /* External */
else if (j == ABSHUNK)
fprintf (f, " Abs"); /* Absolute */
else
fprintf (f, "%4d", j); /* Hunk number */
fprintf (f, " %4d", sym->Defn); /* Statement no. */
}
if (XrefList) {
fprintf (f, " ");
if (sym->Ref1 == 0)
fprintf (f, " *** UNREFERENCED ***");
else {
ref = sym->Ref1;
j = k = 0;
while (1) {
if (ref->RefNum[j] == 0)
break;
if (k >= 9) {
fprintf (f, "\n"); /* New line */
for (k = 0; k < 34; k++)
fprintf (f, " ");
k = 0;
}
fprintf (f, " %4d", ref->RefNum[j]);
j++;
k++;
if (j < MAXREF)
continue; /* Get the next slot */
if ((ref = ref->NextRef) == 0)
break; /* End of last entry */
j = 0; /* Start the next entry */
}
}
}
fprintf (f, "\n");
}
}
CheckPage (f, xhdr) FILE *f; int xhdr;
/* Checks if end of page reached yet -- if so, advances to next page. */
{
LnCnt++;
if (LnCnt >= LnMax) {
PgCnt++;
if (PgCnt > 1)
fprintf (f, "\f"); /* Skip to new page */
fprintf (f, "%-50s", TTLstring); /* Title */
fprintf (f, " %s ", SourceFN); /* File name */
fprintf (f, "Page %d\n\n\n", PgCnt); /* Page number */
LnCnt = 3;
if (xhdr) {
fprintf (f, "Symbol Value Hunk Line");
if (XrefList)
fprintf (f, " References"); /* Cross-reference */
fprintf (f, "\n\n");
LnCnt += 2;
}
}
}
StartSrec (f, idntname) FILE *f; char idntname[];
/* Writes object header record */
{
register int i;
long CheckSum, templong;
if (SFormat) {
fprintf (f, "S0");
templong = strlen (idntname) + 3; /* extra for addr. & checksum */
LongPut (f, templong, 1);
CheckSum = templong;
fprintf (f, "0000"); /* Address is 4 digits, all zero, for S0 */
for (i = 0; idntname[i] != '\0'; i++) {
templong = toupper (idntname[i]);
LongPut (f, templong, 1);
CheckSum += templong;
}
CheckSum = ~CheckSum; /* Complement checksum */
LongPut (f, CheckSum, 1);
fprintf (f, "\n");
} else {
templong = HunkUnit;
putl (f, templong);
DumpName (f, idntname, 0L);
}
StartAddr = TempAddr = Sindex = 0;
NumRExt = NumR32 = NumR16 = NumR8 = 0;
}
WriteSrecLine (f) FILE *f;
/* Transfers object code components to output buffer. */
/* Moves long words or portions thereof. */
{
register int i;
long templong;
if (HunkType == HunkBSS)
return; /* No code in BSS hunk */
if (nO + nS + nD + nX) { /* If we have object code */
if (AddrCnt < TempAddr) { /* and location counter jumped */
if (SFormat) /* and we're making S-format, */
DumpSdata (f); /* get rid of what we have */
StartAddr = TempAddr = AddrCnt; /* and start afresh. */
}
while (AddrCnt >= (TempAddr + 4)) /* It jumped forward - */
AppendSdata (f, 0L, 4); /* fill with zeros */
if (AddrCnt > TempAddr) {
i = AddrCnt - TempAddr;
AppendSdata (f, 0L, i);
}
AppendSdata (f, ObjOp, nO); /* Op code */
AppendSdata (f, ObjSrc, nS); /* Source */
AppendSdata (f, ObjDest, nD); /* Destination */
for (i = 0; i < nX; i++) { /* String data */
templong = ObjString[i];
AppendSdata (f, templong, 1);
}
}
}
AppendSdata (f, Data, n) FILE *f; long Data; int n;
/* If we are producing S-format records:
Transfers "n" low-order bytes from "Data" to the output buffer.
If the buffer becomes full, DumpSdata will be called to flush it.
S-records will also be broken on 16-byte boundaries.
If we are producing AmigaDOS format, data will be written
directly to Srec - we'll go back and fill in the hunk length
at the end of the hunk. */
{
register int i;
register char byte;
long templong;
if (!Pass2)
return; /* Pass 2 only */
if (HunkType == HunkBSS)
return; /* No data in BSS hunks! */
if (HunkType == HunkNone) { /* We're not in a hunk yet - */
ReadSymTab (" "); /* set up pointer */
Sect = Sym; /* to the first section */
HunkType = HunkCode; /* (start a code hunk) */
SectLine = LineCount;
if (!SFormat) {
templong = HunkName;
putl (f, templong);
DumpName (f, " ", 0L);
putl (f, HunkType);
LenPos = ftell (f); /* Hunk length goes here when we get it */
putl (f, 0L); /* For now, set it to zero */
}
}
Data <<= (4 - n) * 8; /* Left-justify data */
for (i = 0; i < n; i++) {
byte = (Data >> ((3 - i) * 8)) & 0x00FF;
TempAddr++;
if (!SFormat)
putc (byte, f);
else {
Sdata[Sindex++] = byte;
if (((TempAddr & 0x0F) == 0) || (Sindex >= MAXSREC))
DumpSdata (f); /* Break S-record */
}
}
}
DumpSdata (f) FILE *f;
/* Writes an object code record */
{
register int i;
register long CheckSum, templong;
if (!SFormat) {
AddrCnt = AddrBndL (AddrCnt); /* Finish last long word */
fseek (f, LenPos, 0); /* Hunk length field is here */
putl (f, ((AddrCnt - SectStart) >> 2) | HunkFlags);
fseek (f, 0L, 2); /* Back to end of file */
DumpRel (f); /* Write relocation information */
TempAddr = AddrCnt;
return;
}
if (Sindex == 0)
return; /* There's nothing to dump */
fprintf (f, "S2");
templong = Sindex + 4; /* Record length */
LongPut (f, templong, 1);
CheckSum = templong; /* Initialize CheckSum */
LongPut (f, StartAddr, 3); /* Address */
CheckSum += (StartAddr >> 16) & 0x00FF;
CheckSum += (StartAddr >> 8) & 0x00FF;
CheckSum += StartAddr & 0x00FF;
for (i = 0; i < Sindex; i++) {
templong = Sdata[i];
LongPut (f, templong, 1); /* Object code */
CheckSum += templong;
}
CheckSum = ~CheckSum; /* Complement checksum */
LongPut (f, CheckSum, 1);
fprintf (f, "\n");
StartAddr += Sindex;
TempAddr = StartAddr;
Sindex = 0;
}
PutRel (f, addr, hunk, size) FILE *f; long addr, hunk; int size;
/* Build a relocation entry if necessary */
{
struct RelTab *rel;
if (!Pass2) return; /* Pass 2 only */
if (SFormat) return; /* Not for S-format! */
if (hunk == ABSHUNK) return; /* Absolute */
if (HunkType == HunkBSS) return; /* Not for BSS hunks! */
HeapSpace (sizeof(struct RelTab)); /* Make sure we have room */
rel = (struct RelTab *) HeapLim; /* Pointer to new entry */
rel->Offset = addr; /* Offset */
rel->Hunk = hunk; /* Hunk number */
rel->Size = size; /* Size */
HeapLim += sizeof(struct RelTab); /* Bump heap limit pointer */
if (hunk < 0) /* Count entries by type */
NumRExt++;
else if (size == Long)
NumR32++;
else if (size == Word)
NumR16++;
else
NumR8++;
}
DumpRel (f) FILE *f;
/* Dump relocation information to the object file. */
{
register struct SymTab *sym;
register struct RelTab *rel, *rel2;
int i, j, size, num, donexhdr, secthlin;
long currhunk, nexthunk, templong;
char *p;
if (SFormat)
return; /* S-format is absolute! */
secthlin = LineCount; /* Current section ends here */
if (strcmp (OpCode,"SECTION") == 0) /* unless we're starting */
secthlin--; /* a new section. */
while (1) {
if ((num = NumR32) != 0) {
size = Long; /* Do 32-bit fields */
templong = HunkR32;
NumR32 = 0; /* ...but only once */
} else if ((num = NumR16) != 0) {
size = Word; /* Then do 16-bit fields */
templong = HunkR16;
NumR16 = 0;
} else if ((num = NumR8) != 0) {
size = Byte; /* Finally do 8-bit fields */
templong = HunkR8;
NumR8 = 0;
} else
break; /* We're all done */
putl (f, templong); /* Record type */
currhunk = 32767;
num = 0;
for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
if ((rel->Size == size) && (rel->Hunk >= 0)) {
if (rel->Hunk < currhunk) {
currhunk = rel->Hunk; /* Lowest hunk number */
num = 1; /* Reset counter */
} else if (rel->Hunk == currhunk) {
num++; /* Count entries */
}
}
}
while (num > 0) { /* Repeat for all hunk references */
templong = num;
putl (f, templong); /* Number of entries */
putl (f, currhunk); /* Hunk number */
nexthunk = 32767;
num = 0; /* Count for next hunk */
for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
if ((rel->Size == size) && (rel->Hunk >= 0)) {
if (rel->Hunk < currhunk)
continue; /* Already wrote it */
else if (rel->Hunk == currhunk)
putl (f, rel->Offset - Sect->Val);
else if (rel->Hunk < nexthunk) {
nexthunk = rel->Hunk; /* Next hunk number */
num = 1; /* Reset counter */
} else if (rel->Hunk == nexthunk) {
num++; /* Count entries */
}
}
}
currhunk = nexthunk; /* Get ready for next hunk */
}
putl (f, 0L); /* End of relocation information */
}
donexhdr = FALSE; /* Haven't written hunk_ext yet */
for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) {
if (sym->Flags & 2) { /* Scan for XDEF symbols */
j = sym->Defn; /* Defined in current section? */
if ((j >= SectLine) && (j <= secthlin)) {
if (!donexhdr) {
templong = HunkExt; /* Haven't done header yet */
putl (f, templong);
donexhdr = TRUE;
}
if ((sym->Hunk & 0x0000FFFFL) == ABSHUNK)
templong = 0x02000000;
else
templong = 0x01000000; /* Flags */
DumpName (f, sym->Nam, templong); /* Symbol */
putl (f, sym->Val - Sect->Val); /* Offset */
}
}
}
if (NumRExt != 0) { /* External references (XREF) */
if (!donexhdr) {
templong = HunkExt; /* Haven't done header yet */
putl (f, templong);
donexhdr = TRUE;
}
for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
if (rel->Hunk < 0) {
p = Heap + ~rel->Hunk;
if (rel->Size == Long)
templong = 0x81000000; /* ext_ref32 */
else if (rel->Size == Word)
templong = 0x83000000; /* ext_ref16 */
else
templong = 0x84000000; /* ext_ref8 */
DumpName (f, p, templong); /* Flags and symbol */
templong = 1;
for (rel2 = rel + 1; rel2 < (struct RelTab *) HeapLim; rel2++)
if (rel2->Hunk == rel->Hunk)
templong++; /* Number of times */
putl (f, templong); /* symbol occurs */
for (rel2 = rel; rel2 < (struct RelTab *) HeapLim; rel2++) {
if (rel2->Hunk == rel->Hunk) {
putl (f, rel2->Offset - Sect->Val); /* Offset */
if (rel2 != rel) /* Kill hunk so we */
rel2->Hunk = 0; /* don't do it again */
} /* (we're done with */
} /* the table anyway) */
}
}
NumRExt = 0;
}
if (donexhdr)
putl (f, 0L); /* End of external information */
if (DumpSym) { /* Dump the symbol table */
donexhdr = FALSE;
for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) {
if ((sym->Hunk == CurrHunk)
&& ((sym->Flags == 0) || (sym->Flags == 2))) {
j = sym->Defn; /* Defined in current section? */
if ((j >= SectLine) && (j <= secthlin)) {
if (!donexhdr) {
templong = HunkSym; /* Header */
putl (f, templong);
donexhdr = TRUE;
}
DumpName (f, sym->Nam, 0L); /* Symbol */
putl (f, sym->Val - Sect->Val); /* Offset */
}
}
}
if (donexhdr)
putl (f, 0L); /* End of symbol table dump */
}
if (HeapLim > HighHeap)
HighHeap = HeapLim; /* High-water mark */
HeapLim = (char *) RelStart; /* Reset heap limit */
}
EndSdata (f, addr) FILE *f; long addr;
/* Write end record to object file */
{
register long checksum, templong;
if (SFormat) {
DumpSdata (Srec); /* Write any remaining data */
fprintf (f, "S804"); /* Record header */
checksum = 4;
LongPut (f, addr, 3); /* Transfer address */
checksum += (addr >> 16) & 0x00FF;
checksum += (addr >> 8) & 0x00FF;
checksum += addr & 0x00FF;
checksum = ~checksum;
LongPut (f, checksum, 1); /* Checksum */
fprintf (f, "\n");
} else {
if (HunkType != HunkNone) {
DumpSdata (Srec); /* Last hunk's data */
templong = HunkEnd; /* End the last hunk */
putl (f, templong);
}
}
}
DumpName (f, name, flags) FILE *f; char name[]; long flags;
/* Writes a name preceded by a long word containing the
length of the name in long words. The length word has
the contents of "flags" ORed into it. The name is padded
with binary zeros to the next long word boundary. */
{
register int i;
register long templong;
templong = (strlen (name) + 3) >> 2; /* Length (long words) */
templong |= flags; /* Add flag bits */
putl (f, templong);
i = 0;
while (name[i])
putc (name[i++], f); /* Write a byte */
while (i & 3) {
putc ('\0', f); /* Pad the last word */
i++;
}
}
LongPut (f, data, length) FILE *f; long data; int length;
/* Writes to file "f" the hexadecimal interpretation of
the bytes in "data". The number of bytes written
(two hex digits per byte) is given in "length" -
if less than 4, only low-order bytes are written. */
{
register int i, j, k;
for (i = length - 1; i >= 0; i--) {
j = (data >> (i * 8)) & 0x00FF;
k = j >> 4;
fprintf (f, "%c", k>9 ? k-10+'A' : k+'0');
k = j & 0x0F;
fprintf (f, "%c", k>9 ? k-10+'A' : k+'0');
}
}
putl (f, data) FILE *f; long data;
/* Writes to file "f" the binary contents of "data" */
{
register int i;
register char byte;
for (i = 0; i < 4; i++) {
byte = (data >> ((3 - i) * 8)) & 0x00FF;
putc (byte, f);
}
}
Error (pos, errornum) int pos, errornum;
/* Displays error #errornum, then waits for any key to continue */
{
register int i;
if (!Pass2)
return; /* Active during pass 2 only */
if (errlim < ERRMAX) { /* Save error data */
errcode[errlim] = errornum;
errpos[errlim] = pos;
errlim++;
}
printf (" \n%4d %s\n", LineCount, Line); /* Line in error */
for (i = 0; i < pos+7; i++)
printf(" ");
printf ("^ "); /* Error flag */
if (errlim == 1) {
if (InF->UPtr == 0)
printf ("%s", InF->NPtr); /* Module name */
else
printf ("(user macro)"); /* In a user macro */
printf (" line %d", InF->Line); /* Line number in module */
}
printf ("\n%s\n", errmsg[errornum]); /* Error message */
ErrorCount++; /* Count errors */
}