/*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Assembler directive processing - September 2, 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 #include "a68kdef.h" #include "a68kglb.h" /* Functions */ extern int LineParts(), GetField(), Instructions(); extern int GetSize(), GetInstModeSize(), GetMultReg(); extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl(); extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue(); extern char *malloc(); extern FILE *fopen(); int ObjDir (f) FILE *f; /* Generates Object Code for Assembler Directives */ { register int i, j; int oploc, dummy; long newflags, templong; char tempop[MAXLINE]; AddrAdv = 0; if (strcmp (OpCode, "ORG") == 0) { /* ORG */ templong = GetValue (SrcOp, SrcLoc); if (Hunk2 < 0) Error (SrcLoc, RelErr); /* Can't ORG externally */ else if (DefLine2 > LineCount) Error (SrcLoc, FwdRef); /* Illegal forward reference */ else { AddrCnt = templong; CurrHunk = Hunk2; } PrntAddr = TRUE; return (Org); } if (strcmp (OpCode, "EQU") == 0) { /* EQU */ if (Label[0] == '\0') Error (0, NeedLab); /* Need a label */ ObjSrc = GetValue (SrcOp, SrcLoc); if (DefLine2 > LineCount) Error (SrcLoc, FwdRef); /* Illegal forward reference */ Src.Hunk = Hunk2; PrntAddr = TRUE; return (Equ); } if (strcmp (OpCode, "DC") == 0) { /* DC */ if ((Size == Word) || (Size == Long)) AddrCnt = AddrBndW (AddrCnt); i = SrcLoc; while ((Line[i] != ' ') && (Line[i] != '\0')) { oploc = i; if (Line[i] == '\'') { /* String */ i++; /* Skip over delimiter */ while (i < strlen(Line)) { if (Line[i] == '\'') { /* End of string? */ i++; /* Check next character */ if (Line[i] != '\'') break; /* End of string */ } /* Otherwise it's an apostrophe in string */ Src.Hunk = ABSHUNK; /* Absolute value */ ObjString[nX++] = Line[i++]; /* Current char. */ } } else { /* Not a string constant */ i = GetField (Line, i, SrcOp); ObjSrc = GetValue (SrcOp, oploc); /* Value */ if ((Src.Hunk = Hunk2) != ABSHUNK) { /* Hunk no. */ templong = AddrCnt + nX; /* Relocatable */ PutRel (Srec, templong, Hunk2, Size); } if (Size == 4) { ObjString[nX++] = (ObjSrc >> 24) & 0x00FF; ObjString[nX++] = (ObjSrc >> 16) & 0x00FF; } if (Size >= 2) ObjString[nX++] = (ObjSrc >> 8) & 0x00FF; ObjString[nX++] = ObjSrc & 0x00FF; } if (Line[i] == ',') i++; /* Skip over separator */ } if ((Line[i] != '\0') && (Line[i] != ' ')) Error (i, OperErr); /* Didn't end properly */ AddrAdv = InstSize = nX; PrntAddr = TRUE; return (DC); } if (strcmp (OpCode, "DS") == 0) { /* DS */ AddrAdv = GetValue (SrcOp, SrcLoc); if (Size == Word) { /* Words */ AddrCnt = AddrBndW (AddrCnt); AddrAdv <<= 1; } if (Size == Long) { /* Long words */ AddrCnt = AddrBndW (AddrCnt); AddrAdv <<= 2; } if (Pass2 && (HunkType != HunkBSS)) { /* If this isn't */ templong = AddrAdv; /* a BSS hunk, */ while (templong >= 4) { /* generate zeros */ AppendSdata (f, 0L, 4); /* to fill the area */ templong -= 4; } if (templong > 0) { i = templong; AppendSdata (f, 0L, i); } } if (DestLoc != 0) Error (DestLoc, OperErr); /* Only one operand is allowed */ PrntAddr = TRUE; return (DS); } if (strcmp (OpCode, "EVEN") == 0) { /* EVEN */ AddrCnt = AddrBndW (AddrCnt); PrntAddr = TRUE; return (Even); } if (strcmp (OpCode, "END") == 0) { /* END */ PrntAddr = TRUE; if (Pass2) if (SrcOp[0] != '\0') EndAddr = GetValue (SrcOp, SrcLoc); else EndAddr = 0; return (End); } if (strcmp (OpCode, "XDEF") == 0) { /* XDEF */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ i = SrcLoc; while ((Line[i] != ' ') && (Line[i] != '\0')) { oploc = i; i = GetField (Line, i, SrcOp); /* Get a symbol */ if (ReadSymTab (SrcOp)) { if (!Pass2) { if ((Sym->Flags & 0x60) == 0) Sym->Flags |= 2; /* Set XDEF flag */ } else { AddRef (LineCount); if (Sym->Defn == 0) Error (oploc, Undef); /* Never got defined */ else if (Sym->Flags & 0x60) Error (oploc, AddrErr); /* Can't XDEF a register */ } } else if (!Pass2) { /* Not yet defined */ AddSymTab (SrcOp, 0L, CurrHunk, 0, 2); } if (Line[i] == ',') i++; /* Skip over separator */ } return (Xdef); } if (strcmp (OpCode, "XREF") == 0) { /* XREF */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ i = SrcLoc; while ((Line[i] != ' ') && (Line[i] != '\0')) { oploc = i; i = GetField (Line, i, SrcOp); if (Pass2) { if (ReadSymTab (SrcOp) && (Sym->Defn != LineCount)) { AddRef (LineCount); /* Ignore extraneous XREF */ } } else { if (!ReadSymTab (SrcOp)) { /* Only if not */ templong = ~(HeapLim - Heap); /* defined */ templong &= 0x0000FFFF; AddSymTab (SrcOp, 0L, templong, LineCount, 1); } } if (Line[i] == ',') i++; /* Skip over separator */ } return (Xref); } if (strcmp (OpCode, "PAGE") == 0) { /* PAGE */ if (Pass2) LnCnt = LnMax; /* Resume on a new page */ return (Page); } if (strcmp (OpCode, "LIST") == 0) { /* LIST */ ListOff = FALSE; return (DoList); } if ((strcmp(OpCode,"NOLIST")==0) || (strcmp(OpCode,"NOL")==0)) { ListOff = TRUE; /* NOLIST */ return (NoList); } if (strcmp (OpCode, "SPC") == 0) { /* SPC */ if (Pass2 && !ListOff && !SuppList) { if (SrcOp[0] != '\0') j = GetValue (SrcOp, SrcLoc); /* Amount to space */ else j = 1; /* Default to one line */ for (i = 0; i < j; i++) { if (LnCnt >= LnMax) break; /* Page overflow */ fprintf (List, "\n"); /* Space one line */ } } return (Space); } if (strcmp (OpCode, "TTL") == 0) { /* TTL */ for (i = SrcLoc, j = 0; Line[i] != '\0'; i++) { TTLstring[j++] = Line[i]; /* Get title string */ if (j >= MAXLINE - 1) break; /* The string is full */ } TTLstring[j] = '\0'; LnCnt = LnMax; /* Skip to a new page */ return (Title); } if (strcmp (OpCode, "CNOP") == 0) { /* CNOP */ i = TRUE; /* "Error-free" flag */ ObjSrc = GetValue (SrcOp, SrcLoc); if (DefLine2 > LineCount) { Error (SrcLoc, FwdRef); /* Illegal forward reference */ i = FALSE; } if (Hunk2 != ABSHUNK) { Error (SrcLoc, AbsReq); /* Must be absolute! */ i = FALSE; } ObjDest = GetValue (DestOp, DestLoc); if (DefLine2 > LineCount) { Error (DestLoc, FwdRef); /* Illegal forward reference */ i = FALSE; } if (Hunk2 != ABSHUNK) { Error (DestLoc, AbsReq); /* Must be absolute! */ i = FALSE; } if ((ObjDest != 2) && (ObjDest != 4)) { Error (DestLoc, OperErr); /* DestOp must be 2 or 4 */ i = FALSE; } if (((ObjSrc != 0) && (ObjSrc != 2)) || (ObjSrc >= ObjDest)) { Error (SrcLoc, OperErr); /* SrcOp must be 0 or 2 */ i = FALSE; } if (i) { /* If no errors... */ AddrCnt = AddrBndW (AddrCnt); if ((AddrCnt & 3L) != ObjSrc) { /* and not aligned */ ObjOp = NOP; AddrAdv = InstSize = nO = 2; /* generate a NOP */ PrntAddr = TRUE; } } return (Cnop); } if (strcmp (OpCode, "INCLUDE") == 0) { /* INCLUDE */ i = SrcLoc; if ((Line[i]=='"') || (Line[i]=='\'')) i++; /* Ignore quotes */ j = 0; while ((Line[i] != ' ') && (Line[i] != '"') && (Line[i] != '\'') && (Line[i] != '\0')) tempop[j++] = Line[i++]; tempop[j] = '\0'; if (InF->UPtr == 0) InF->Pos = ftell(InFile); /* Position in outer file */ if (!OpenIncl (tempop, InclList)) { Error (SrcLoc, NoIncl); /* Couldn't open file */ if (InF->UPtr == 0) { InFile = fopen (InF->NPtr, "r"); fseek (InFile, InF->Pos, 0); } return (Include); /* Return to outer file */ } InFNum++; /* Bump nesting level */ if (--InF < LowInF) LowInF = InF; Heap2Space (strlen (tempop) + 1); /* Check for space */ InF->UPtr = 0; /* Not a user macro */ InF->NPtr = NextFNS; /* New stack pointer */ strcpy (NextFNS, tempop); /* File name */ NextFNS += strlen (tempop) + 1; /* Next available space */ if (NextFNS > High2) High2 = NextFNS; /* Set high-water mark */ InF->NArg = -1; /* Flag as an INCLUDE */ InF->Line = 0; /* Clear line counter */ return (Include); } if (strcmp (OpCode, "SET") == 0) { /* SET */ if (Label[0] == '\0') Error (0, NeedLab); /* Need a label */ ObjSrc = GetValue (SrcOp, SrcLoc); if (DefLine2 > LineCount) Error (SrcLoc, FwdRef); /* Illegal forward reference */ Src.Hunk = Hunk2; PrntAddr = TRUE; if (!ReadSymTab (Label)) /* Make a new entry */ AddSymTab (Label, ObjSrc, Src.Hunk, LineCount, 4); else if (Sym->Flags & 4) { /* Re-SET the symbol */ Sym->Val = ObjSrc; /* SET value */ Sym->Hunk = Src.Hunk; /* Hunk number */ Sym->Defn = LineCount; /* Statement number */ } return (Set); } if (strcmp (OpCode, "MACRO") == 0) { /* MACRO */ Dir = Macro; tempop[0] = ' '; i = 0; /* Prepend name with a */ j = 1; /* blank and convert */ while (Label[i]) /* it to upper case */ tempop[j++] = toupper (Label[i++]); tempop[j] = '\0'; if (!Pass2) { /* Pass 1 */ if (Label[0] != '\0') { /* Need a label */ templong = HeapLim - Heap; /* Offset to text */ if (!ReadSymTab (tempop)) /* Save MACRO name */ AddSymTab (tempop, 0L, templong, LineCount, 8); AddMacLine (Line); /* Save MACRO stmt. */ while (strcmp (OpCode, "ENDM")) { if (LineParts (dummy)) break; /* Premature EOF */ AddMacLine (Line); /* Store a line */ } } } else { /* Pass 2 */ if (Label[0] == '\0') Error (0, NeedLab); /* Need a label */ else { ReadSymTab (tempop); if (Sym->Defn != LineCount) { Error (0, DupMac); /* Duplicate MACRO */ AddRef (LineCount); } } if (!SuppList) WriteListLine (List); /* Echo MACRO */ while (1) { if (LineParts (dummy)) { Error (OpLoc, NoENDM); /* Premature EOF */ break; } else { if (strcmp (OpCode, "ENDM") == 0) break; if (!SuppList) WriteListLine (List); /* Echo a line */ } } } return (Macro); } if (strcmp (OpCode, "IFEQ") == 0) { /* IFEQ */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc != 0) SkipNest++; /* Skip to the next ENDC */ return (If); } if (strcmp (OpCode, "IFNE") == 0) { /* IFNE */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc == 0) SkipNest++; return (If); } if (strcmp (OpCode, "IFGT") == 0) { /* IFGT */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc <= 0) SkipNest++; return (If); } if (strcmp (OpCode, "IFGE") == 0) { /* IFGE */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc < 0) SkipNest++; return (If); } if (strcmp (OpCode, "IFLT") == 0) { /* IFLT */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc >= 0) SkipNest++; return (If); } if (strcmp (OpCode, "IFLE") == 0) { /* IFLE */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc > 0) SkipNest++; return (If); } if (strcmp (OpCode, "IFC") == 0) { /* IFC */ if (strcmp (SrcOp, DestOp) != 0) SkipNest++; return (If); } if (strcmp (OpCode, "IFNC") == 0) { /* IFNC */ if (strcmp (SrcOp, DestOp) == 0) SkipNest++; return (If); } if (strcmp (OpCode, "IFD") == 0) { /* IFD */ if (ReadSymTab (SrcOp)) AddRef (LineCount); if (DefLine2 > LineCount) SkipNest++; return (If); } if (strcmp (OpCode, "IFND") == 0) { /* IFND */ if (ReadSymTab (SrcOp)) AddRef (LineCount); if (DefLine2 <= LineCount) SkipNest++; return (If); } if (strcmp (OpCode, "ENDC") == 0) /* ENDC */ return (EndC); /* Just ignore it */ if ((strcmp (OpCode, "CODE") == 0) /* CODE */ || (strcmp (OpCode, "DATA") == 0) /* DATA */ || (strcmp (OpCode, "BSS") == 0)) { /* BSS */ strcpy (DestOp, OpCode); /* Convert to corresponding */ strcpy (OpCode, "SECTION"); /* SECTION directive */ } if (strcmp (OpCode, "SECTION") == 0) { /* SECTION */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ PrntAddr = TRUE; for (i = 0; DestOp[i]; i++) /* Convert section type */ DestOp[i] = toupper (DestOp[i]); /* to upper case */ if ((DestOp[0] == '\0') || (strcmp (DestOp, "CODE") == 0)) newflags = HunkCode; /* Code section */ else if (strcmp (DestOp, "DATA") == 0) newflags = HunkData; /* Data section */ else if (strcmp (DestOp, "BSS") == 0) newflags = HunkBSS; /* BSS section */ else { Error (DestLoc, OperErr); /* Invalid type */ strcpy (DestOp, "CODE"); newflags = HunkCode; /* Make it CODE */ } newflags <<= 16; /* Shift to high-order 16 bits */ tempop[0] = '\0'; j = DestLoc + strlen (DestOp); /* Check for flags */ if (Line[j] == ',') { j++; GetField (Line, j, tempop); /* Get specification */ for (i = 0; tempop[i]; i++) /* Convert to */ tempop[i] = toupper (tempop[i]); /* upper case */ if (strcmp (tempop, "CHIP") == 0) newflags |= MEMF_CHIP; /* CHIP memory */ else if (strcmp (tempop, "FAST") == 0) newflags |= MEMF_FAST; /* FAST memory */ else Error (j, OperErr); /* Invalid */ } if (SrcOp[0] == '\0') { /* Unnamed section */ if ((strcmp (DestOp, "DATA") == 0) || (strcmp (DestOp, "BSS") == 0)) { Error (SrcLoc, NoSecNam); /* Must be named */ return (Section); } } AddrCnt = AddrBndL (AddrCnt); /* Finish on long word */ strcpy (tempop, " "); /* Two leading blanks */ strcat (tempop, SrcOp); /* Section name */ if (ReadSymTab (tempop)) { /* Scan for section name */ if ((Sym->Hunk & 0xFFFF0000L) != (newflags & 0xFFFF0000L)) { Error (DestLoc, WrongTyp); /* Continuation in a */ return (Section); /* different type */ } if (HunkType != HunkNone) { if (Pass2) { AddRef (LineCount); DumpSdata (Srec); /* Previous hunk's data */ if (!SFormat) { templong = HunkEnd; /* End of */ putl (Srec, templong); /* previous hunk */ } } Sect->Val = AddrCnt; /* End of old section */ } Sect = Sym; /* Point to new section */ SectLine = LineCount; AddrCnt = SectStart = Sym->Val; /* Continuation */ TempAddr = StartAddr = AddrCnt; CurrHunk = Sym->Hunk & 0x0000FFFFL; /* Hunk no. */ HunkType = (Sym->Hunk & 0x3FFF0000L) >> 16; /* Type */ HunkFlags = Sym->Hunk & 0xC0000000L; /* Flags */ if (Pass2 && !SFormat) { /* Start a new hunk */ templong = HunkName; putl (f, templong); if (SrcOp[0]) DumpName (f, SrcOp, 0L); /* Hunk name */ else DumpName (f, " ", 0L); putl (f, HunkType); /* Hunk type */ LenPos = ftell (f); /* Hunk length goes here */ putl (f, 0L); /* For now, set it to zero */ } return (Section); } if (Pass2) { Error (OpLoc, ManySect); /* Table overflowed in pass 1 */ return (Section); } if (NextHunk >= ABSHUNK) /* Set up a new table entry */ return (Section); /* Section table overflow */ if (HunkType != HunkNone) Sect->Val = AddrCnt; /* End of old section */ AddrCnt = SectStart = 0L; /* Reset location counter */ TempAddr = StartAddr = AddrCnt; HunkType = (newflags & 0x3FFF0000L) >> 16; /* Type */ HunkFlags = newflags & 0xC0000000L; /* Flags */ SectLine = LineCount; /* Starting line number */ CurrHunk = NextHunk++; /* Bump next hunk number */ newflags |= CurrHunk; /* Add hunk number */ AddSymTab (tempop, 0L, newflags, LineCount, 16); /* New entry */ Sect = Sym; /* Pointer to new entry */ return (Section); } if (strcmp (OpCode, "IDNT") == 0) { /* IDNT */ i = SrcLoc; if (Line[i] == '"') i++; /* Ignore quotation marks */ j = 0; while ((Line[i] != ' ') && (Line[i] != '"') && (Line[i] != '\0')) IdntName[j++] = Line[i++]; IdntName[j] = '\0'; return (Idnt); } if (strcmp (OpCode, "DCB") == 0) { /* DCB */ if ((Size == Word) || (Size == Long)) AddrCnt = AddrBndW (AddrCnt); ObjSrc = GetValue (SrcOp, SrcLoc); /* Replication factor */ if (DefLine2 > LineCount) { Error (SrcLoc, FwdRef); /* Illegal forward reference */ ObjSrc = 0; } if (Hunk2 != ABSHUNK) { Error (SrcLoc, AbsReq); /* Must be absolute! */ ObjSrc = 0; } ObjDest = GetValue (DestOp, DestLoc); /* Value to replicate */ Dest.Hunk = Hunk2; for (i = 0; i < ObjSrc; i++) { if (nX >= MAXLINE) { Error (SrcLoc, DCOflo); /* ObjString overflowed */ break; } if (Dest.Hunk != ABSHUNK) { templong = AddrCnt + nX; /* Relocatable */ PutRel (Srec, templong, Hunk2, Size); } if (Size == 4) { ObjString[nX++] = (ObjDest >> 24) & 0x00FF; ObjString[nX++] = (ObjDest >> 16) & 0x00FF; } if (Size >= 2) ObjString[nX++] = (ObjDest >> 8) & 0x00FF; ObjString[nX++] = ObjDest & 0x00FF; } AddrAdv = InstSize = nX; PrntAddr = TRUE; return (DCB); } if (strcmp (OpCode, "EQUR") == 0) { /* EQUR */ if ((i = IsRegister (SrcOp, strlen (SrcOp))) < 0) Error (SrcLoc, AddrErr); /* Not a valid register */ if (Label[0] == '\0') Error (0, NeedLab); /* Need a label */ else { if (!ReadSymTab (Label)) /* Make a new entry */ AddSymTab (Label, (long) i, 0L, LineCount, 0x20); GotEqur = TRUE; /* We have at least one EQUR */ } return (Equr); } if (strcmp (OpCode, "REG") == 0) { /* REG */ if (Label[0] == '\0') Error (0, NeedLab); /* Need a label */ else { i = GetMultReg (SrcOp, FALSE, SrcLoc); if (!ReadSymTab (Label)) /* Make a new entry */ AddSymTab (Label, (long) i, 0L, LineCount, 0x40); GotEqur = TRUE; /* We have at least one EQUR */ } return (Reg); } return (None); /* Not a directive */ }