page@swan.ulowell.edu (Bob Page) (03/08/89)
Submitted-by: jlydiatt@jlami.wimsey.bc.ca (Jeff Lydiatt) Posting-number: Volume 89, Issue 25 Archive-name: languages/a68k242.3 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # A68kdef.h # Adirect.c # Codegen.c # Opcodes.c # This archive created: Tue Mar 7 20:42:01 1989 cat << \SHAR_EOF > A68kdef.h /*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* #define statements - January 6, 1989 */ /* */ /* 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 1989 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ #ifdef AZTEC_C #include <ctype.h> #endif extern char *malloc(); extern int open(), creat(), read(), write(), close(), unlink(); extern long lseek(); #define TRUE 1 #define FALSE 0 #define NODEF 32767 /* High line number for undefined symbols */ /* Assembler configuration parameters */ #define MAXLINE 128 /* Longest source line */ #define MAXFN 41 /* Maximum length of file name */ #define MAXSREC 16 /* Maximum S-record data length */ #define MAXREF 4 /* Number of line numbers in reference entry */ #define DEFHASH 2047 /* Default number of elements in hash table */ #define DEFHEAP2 1024 /* Default size for secondary heap */ #define INCSKSIZ 2048 /* Size of INCLUDE skip table */ #ifdef MSDOS #define CHUNKSIZE 2048 /* Memory chunks for Itty Bitty Memories */ #else #define CHUNKSIZE 8192 /* Size of memory chunks allocated for tables */ #endif #define BUFFSIZE 2048 /* File buffer size */ #define ObjMAX 32 /* Max. hex object code digits in listing */ /* Hunk number definitions */ #define HunkNone 0 /* Not in a hunk */ #define HunkUnit 999 #define HunkName 1000 #define HunkCode 1001 #define HunkData 1002 #define HunkBSS 1003 #define HunkR32 1004 #define HunkR16 1005 #define HunkR8 1006 #define HunkExt 1007 #define HunkSym 1008 #define HunkDbg 1009 #define HunkEnd 1010 #define MEMF_FAST 0x80000000L /* Hunk must load in FAST memory */ #define MEMF_CHIP 0x40000000L /* Hunk must load in CHIP memory */ /* Hunk numbers denoting special symbol attributes */ #define ABSHUNK 32767 /* Absolute */ /* Addressing mode flag values */ #define DReg 1 /* Data Register */ #define ARDir 2 /* Address Register Direct */ #define ARInd 3 /* Address Register Indirect */ #define ARPost 4 /* Address Register with Post-Increment */ #define ARPre 5 /* Address Register with Pre-Decrement */ #define ARDisp 6 /* Address Register with Displacement */ #define ARDisX 7 /* Address Register with Disp. & Index */ #define AbsW 8 /* Absolute Short (16-bit Address) */ #define AbsL 9 /* Absolute Long (32-bit Address) */ #define PCDisp 10 /* Program Counter Relative, with Displacement */ #define PCDisX 11 /* Program Counter Relative, with Disp. & Index */ #define Imm 12 /* Immediate */ #define MultiM 13 /* Multiple Register Move */ #define SR 14 /* Status Register */ #define CCR 15 /* Condition Code Register */ #define USP 16 /* User's Stack Pointer */ #define Null 0 /* Error Condition, or Operand missing */ #define X0 0 /* Register types */ #define Dreg 1 #define Areg 2 #define S0 0 /* Size types */ #define Byte 1 #define Word 2 #define S3 3 #define Long 4 #define CMPM 0xB108 #define JMP 0x4EC0 #define JSR 0x4E80 #define LEA 0x41C0 #define LINK 0x4E50 #define NOP 0x4E71 #define PEA 0x4840 #define STOP 0x4E72 #define SWAP 0x4840 #define UNLK 0x4E58 #define None 0 /* Assembler directives */ #define Org 1 #define DC 2 #define DS 3 #define Even 4 #define End 5 #define Cnop 6 #define Section 7 #define CSeg 8 #define DSeg 9 #define BSS 10 #define Idnt 11 #define DCB 12 #define Near 13 #define Far 14 #define BadMac 15 #define SkipDir 16 /* Skippable INCLUDE directives start here */ #define Equ 16 #define Public 17 #define Xdef 18 #define Xref 19 #define Page 20 #define DoList 21 #define NoList 22 #define Space 23 #define Title 24 #define Include 25 #define Set 26 #define Macro 27 #define IfEQ 28 #define IfNE 29 #define IfGT 30 #define IfGE 31 #define IfLT 32 #define IfLE 33 #define IfC 34 #define IfNC 35 #define IfD 36 #define IfND 37 #define EndC 38 #define Equr 39 #define Reg 40 #define MacCall 41 /* BITSETs of the modes MISSING from effective address modes */ #define ea 0x0000 /* Effective addressing - all modes */ #define dea 0x0002 /* Data effective addressing */ #define mea 0x0003 /* Memory effective addressing */ #define cea 0x081B /* Control effective addressing */ #define aea 0x0E00 /* Alterable effective addressing */ #define xxx 0xE000 /* extra modes: CCR/SR/USP */ #define IN & /* Simulated BITSET test */ /* AdrModeA bit definitions */ #define RegMem3 0x0001 /* 0 = register, 1 = memory */ #define Ry02 0x0002 /* Register Rx - bits 0-2 */ #define Rx911 0x0004 /* Register Ry - bits 9-11 */ #define Data911 0x0008 /* Immediate data - bits 9-11 */ #define CntR911 0x0010 /* Count register or immediate data */ #define Brnch 0x0020 /* Relative branch */ #define DecBr 0x0040 /* Decrement and branch */ #define Data03 0x0080 /* TRAP vector in 0-3 */ #define Data07 0x0100 /* Data in 0-7 (MOVEQ) */ #define OpM68D 0x0200 /* Data register in 6-8 */ #define OpM68A 0x0400 /* Address register in 6-8 (ADDA/CMPA/SUBA) */ #define OpM68C 0x0800 /* CMP (Compare) */ #define OpM68X 0x1000 /* EOR (Exclusive or) */ #define OpM68S 0x2000 /* EXT (Sign extension) */ #define OpM68R 0x4000 /* MOVEP (Register/memory) */ #define OpM37 0x8000 /* EXG (Exchange registers) */ #define TwoOpsA 0xDF4D /* Two operands are required */ /* AdrModeB bit definitions */ #define Bit811 0x0001 /* Bit operations - bits 8-11 as switch */ #define Size67 0x0002 /* 00 = byte, 01 = word, 10 = long */ #define Size6 0x0004 /* 0 = word, 1 = long */ #define Sz1213A 0x0008 /* 01 = byte, 11 = word, 10 = long */ #define Sz1213 0x0010 /* 11 = word, 10 = long */ #define Exten 0x0020 /* Opcode extension is required */ #define EA05a 0x0040 /* Effective address - all */ #define EA05b 0x0080 /* All except ARDir */ #define EA05c 0x0100 /* All except ARDIR and Imm */ #define EA05d 0x0200 /* All except PCDisp, PCDisx, and Imm */ #define EA05e 0x0400 /* All except ARDir, PCDisp, PCDisx, and Imm */ #define EA05f 0x0800 /* All except Dreg, ARDir, ARPost, ARPre, Imm */ #define EA05x 0x1000 /* Dual mode - AND/OR */ #define EA05y 0x2000 /* Dual mode - ADD/SUB */ #define EA05z 0x4000 /* Dual mode - MOVEM */ #define EA611 0x8000 /* Eff. Adr. in 6-11 (used only by MOVE) */ #define TwoOpsB 0xF3DD /* Two operands are required */ #define ImmMode 0x0422 /* Immediate instructions */ #define SrcPC 0xF8C0 /* Source operand may be PCDisp */ #define Dummy 0 /* Error codes */ #define AlignErr 1 #define NoCode 2 #define SymDup 3 #define Undef 4 #define ModeErr 5 #define OperErr 6 #define BraErr 7 #define AddrErr 8 #define SizeErr 9 #define EndErr 10 #define AbsReq 11 #define RelErr 12 #define NoIncl 13 #define FwdRef 14 #define NotSFmt 15 #define NeedLab 16 #define Phase 17 #define NoENDM 18 #define NoENDC 19 #define ManyENDC 20 #define DCOflo 21 #define ManySect 22 #define DupMac 23 #define MultLab 24 #define NoStrEnd 25 #define BccSDsp0 26 #define ERRMAX 10 /* Size of error message table */ SHAR_EOF cat << \SHAR_EOF > Adirect.c /*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Assembler directive processing - January 6, 1989 */ /* */ /* 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 1989 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ #include <stdio.h> #include "a68kdef.h" #include "a68kglb.h" /* Functions */ extern int LineParts(), Instructions(); extern int GetInstModeSize(), GetMultReg(), CountNest(); extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl(); extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue(); extern char *AddName(), *GetField(); extern struct SymTab *NextSym(); extern struct SymTab **HashIt(); int ObjDir (dummy) int dummy; /* Generates Object Code for Assembler Directives */ { register char *s, *t; register int i, j; int oploc; long templong; char tempop[MAXLINE], delim; struct SetFixup *sf; switch (Dir) { case Org: /* ORG */ PrntAddr = MakeHunk = TRUE; templong = GetValue (SrcOp, SrcLoc); if (DefLine2 >= LineCount) { Error (SrcLoc, FwdRef); /* Illegal forward reference */ break; } if (OpCode[0] == 'R') { /* RORG */ if (Hunk2 != ABSHUNK) { Error (SrcLoc, RelErr); /* RORG needs absolute value */ break; } } else if (Hunk2 != CurrHunk) { Error (SrcLoc, RelErr); /* Can't ORG out of hunk */ break; } if ((!Pass2 || (HunkType == HunkBSS)) && (templong < AddrCnt) /* If we're ORGing to a lower address */ && (AddrCnt > OrgHigh)) /* and this is the highest we've been */ OrgHigh = AddrCnt; /* remember how far we got. */ AddrCnt = templong; /* Update the location counter */ OrgFlag = TRUE; /* Indicate object fixups are needed */ break; case Equ: /* 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 = MakeHunk = TRUE; break; case DC: /* DC */ if ((Size == Word) || (Size == Long)) AddrCnt = AddrBndW (AddrCnt); s = Line + SrcLoc; while (!isspace(*s) && (*s != '\0') && (*s != ';')) { oploc = s - Line; if (((*s == '\'') || (*s == '"')) /* String */ && (Size == Byte)) { delim = *s++; /* Get the delimiter */ while (1) { if (*s == '\0') { /* No closing delimiter */ Error (s-Line, NoStrEnd); break; } if (*s == delim) { /* End of string? */ if (*(++s) != delim) /* Check next character */ break; /* End of string */ } /* Otherwise it's an apostrophe in the string */ Src.Hunk = ABSHUNK; /* Absolute value */ ObjString[nX++] = *s++; /* Current character */ } } else { /* Not a string constant */ s = GetField (s, SrcOp); ObjSrc = GetValue (SrcOp, oploc); /* Value */ if ((Src.Hunk = Hunk2) != ABSHUNK) { /* Hunk no. */ templong = AddrCnt + nX; /* Relocatable */ PutRel (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 (Size == 2) templong = 0xFFFF0000L; else if (Size == 1) templong = 0xFFFFFF00L; if (Size < 4) if (((ObjSrc & templong) != 0) && ((ObjSrc & templong) != templong)) Error (s-Line, SizeErr); } if (*s == ',') s++; /* Skip over separator */ } if (!isspace(*s) && (*s != '\0') && (*s != ';')) Error (s-Line, OperErr); /* Didn't end properly */ AddrAdv = InstSize = nX; PrntAddr = MakeHunk = TRUE; break; case DS: /* DS */ if (DestLoc != 0) { Error (DestLoc, OperErr); /* Only one operand is allowed */ PrntAddr = MakeHunk = TRUE; break; } AddrAdv = GetValue (SrcOp, SrcLoc); if (DefLine2 >= LineCount) { Error (SrcLoc, FwdRef); /* Illegal forward reference */ AddrAdv = 0; } if (Hunk2 != ABSHUNK) Error (SrcLoc, AbsReq); /* Count must be absolute */ 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 (0L, 4); /* to fill the area */ templong -= 4; } if (templong > 0) { i = templong; AppendSdata (0L, i); } } PrntAddr = MakeHunk = TRUE; break; case Even: /* EVEN */ AddrCnt = AddrBndW (AddrCnt); PrntAddr = MakeHunk = TRUE; break; case End: /* END */ if (Pass2) if (SrcOp[0] != '\0') EndAddr = GetValue (SrcOp, SrcLoc); else EndAddr = 0; PrntAddr = MakeHunk = TRUE; break; case Xdef: /* XDEF */ case Public: /* PUBLIC */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ s = Line + SrcLoc; while (!isspace(*s) && (*s != '\0')) { oploc = s - Line; s = GetField (s, SrcOp); /* Get a symbol */ if (ReadSymTab (SrcOp)) { if (!Pass2) { if ((Sym->Flags & 0x61) == 0) { Sym->Flags |= 2; /* Set XDEF flag */ if (OpCode[0] == 'P') { Sym->Flags |= 0x80; /* Defined as PUBLIC */ } } } else { if (Sym->Defn != LineCount) /* If not PUBLIC->XREF */ AddRef (LineCount); /* it's a reference */ if (Sym->Defn == NODEF) 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 */ if (OpCode[0] == 'P') { /* Treat PUBLIC as XREF */ AddSymTab (SrcOp, 0L, 0L ,LineCount, 0x81); Sym->Hunk = ~((long) Sym->Nam); } else { AddSymTab (SrcOp, 0L, CurrHunk, NODEF, 2); /* XDEF */ } } if (*s == ',') s++; /* Skip over separator */ } break; case Xref: /* XREF */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ s = Line + SrcLoc; while (!isspace(*s) && (*s != '\0')) { oploc = s - Line; s = GetField (s, SrcOp); if (Pass2) { if (ReadSymTab (SrcOp)) { if (Sym->Defn != LineCount) { AddRef (LineCount); /* Ignore extraneous XREF */ } } } else { if (!ReadSymTab (SrcOp)) { /* Only if not defined */ AddSymTab (SrcOp, 0L, 0L, LineCount, 1); Sym->Hunk = ~((long) Sym->Nam); } } if (*s == ',') s++; /* Skip over separator */ } break; case Page: /* PAGE */ if (Pass2 && (LineCount > 1)) /* Ignore PAGE at start of file */ LnCnt = LnMax; /* Resume on a new page */ break; case DoList: /* LIST */ ListOff = FALSE; if (!Pass2 && !SuppList && (IncStart != 0)) { IncStart = 0; /* We can't */ if (SkipLim->Set1 != NULL) { /* skip this */ SetFixLim = SkipLim->Set1; /* INCLUDE file */ SetFixLim++; /* in pass 2 */ } /* (we must */ } /* list it). */ break; case NoList: /* NOLIST */ ListOff = TRUE; break; case Space: /* 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 */ xputs (&List, "\n"); /* Space one line */ } } break; case Title: /* TTL */ s = Line + SrcLoc; t = TTLstring; while (*s && (s < (TTLstring+MAXLINE))) *t++ = *s++; /* Get title string */ *t = '\0'; if (LineCount > 1) { LnCnt = LnMax; /* Skip to a new page */ } else { if (Pass2) { xputs (&List, TTLstring); xputs (&List, "\n\n"); } LnCnt += 2; /* Don't skip at start of file */ } break; case Cnop: /* 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; } templong = ObjDest; while ((templong > 0) && ((templong & 1) == 0)) templong >>= 1; /* Shift out low-order zeros */ if ((templong != 1) || (ObjDest == 1)) { Error (DestLoc, OperErr); /* DestOp must be a power of 2 */ i = FALSE; } if ((ObjSrc & 1) || (ObjSrc >= ObjDest)) { Error (SrcLoc, OperErr); /* SrcOp is odd or out of range */ i = FALSE; } if (i) { /* If no errors so far */ AddrCnt = AddrBndW (AddrCnt); templong = (AddrCnt & ~(ObjDest-1)) + ObjSrc; if (templong < AddrCnt) templong += ObjDest; /* We must advance to here */ if ((templong - AddrCnt) < MAXLINE) { nX = templong - AddrCnt; for (j = 0; j < nX; ) { ObjString[j++] = NOP / 256; ObjString[j++] = NOP & 255; } AddrAdv = InstSize = nX; /* generate NOPs */ PrntAddr = MakeHunk = TRUE; } else { Error (DestLoc, OperErr); /* Too many NOPs */ } } break; case Include: /* INCLUDE */ if (Pass2 /* If we can skip */ && (SkipIdx < SkipLim) /* this INCLUDE */ && (LineCount == SkipIdx->Start)) { /* file in pass */ LineCount = SkipIdx->Finish; /* 2, do so. */ MacCount = SkipIdx->MCount; if ((sf = SkipIdx->Set1) != NULL) { while ((sf >= SetFixLim) && (sf->Sym != NULL)) { (sf->Sym)->Val = sf->Val; /* Fix up SET symbols */ (sf->Sym)->Hunk = sf->Hunk; sf--; } } SkipIdx++; break; } if ((Quiet < 0) && (InF->UPtr == 0)) ShowLine (InF->Line); /* Show where we are */ s = Line + SrcLoc; if ((*s == '"') || (*s == '\'')) s++; /* Ignore quotes */ t = tempop; while (!isspace(*s) && (*s != '"') && (*s != '\'') && (*s != '\0')) *t++ = *s++; *t = '\0'; if (InF->UPtr == 0) { InF->Pos = lseek (In.fd, 0L, 1); InF->Pos -= In.Lim-In.Ptr; /* Position in outer file */ } if (!OpenIncl (tempop, InclList)) { Error (SrcLoc, NoIncl); /* Couldn't open file */ InclErrs = TRUE; if (InF->UPtr == 0) { In.fd = open (InF->NPtr, 0); lseek (In.fd, InF->Pos, 0); In.Ptr = In.Lim = In.Buf; } break; /* 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; /* Indicate it's not a macro */ InF->Line = 0; /* Clear line counter */ InF->MCnt = MacCount; if (!Pass2 && (SuppList || ListOff) && (IncStart == 0)) { s = (char *) SkipLim + sizeof (struct SkipEnt); if (s <= (char *) SetFixLim) { SkipLim->Set1 = NULL; /* Save starting position */ IncStart = LineCount; /* in case we can skip */ IncPtr = InF; /* this file in pass 2. */ } } break; case Set: /* 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; 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 */ } PrntAddr = MakeHunk = TRUE; if (!Pass2 && (IncStart != 0)) { if ((sf = SkipLim->Set1) != NULL) { while (sf >= SetFixLim) { if (sf->Sym != Sym) { sf--; } else { sf->Val = Sym->Val; /* Update an */ sf->Hunk = Sym->Hunk; /* existing entry. */ return (Set); } } } sf = SetFixLim; sf--; s = (char *) SkipLim + sizeof (struct SkipEnt); if (s > (char *) sf) { IncStart = 0; /* No room for set symbol */ if (SkipLim->Set1 != NULL) { SetFixLim = SkipLim->Set1; SetFixLim++; } } else { if (SkipLim->Set1 == NULL) SkipLim->Set1 = sf; /* First SET symbol in INCLUDE */ sf->Sym = Sym; sf->Val = Sym->Val; /* Save SET symbol value */ sf->Hunk = Sym->Hunk; /* and hunk. */ SetFixLim = sf; } } break; case Macro: /* MACRO */ if (Label[0] == '\0') Error (0, NeedLab); /* Need a label */ s = Label; t = tempop; *t++ = ' '; /* Prepend name with a */ while (*s) /* blank and convert */ *t++ = toupper (*s++); /* it to upper case. */ *t = '\0'; if (!Pass2) { /* Pass 1 */ if (!ReadSymTab (tempop)) /* Save MACRO name */ AddSymTab (tempop, 0L, 0L, LineCount, 8); Sym->Hunk = (long) AddName(Line,1); /* Save MACRO stmt. */ } else { /* Pass 2 */ ReadSymTab (tempop); if (Sym->Defn != LineCount) { Error (LabLoc, DupMac); /* Duplicate MACRO */ AddRef (LineCount); } WriteListLine (&List); /* Echo MACRO */ } i = 0; /* IF nest counter */ while (1) { /* Process macro body */ if (LineParts (dummy)) { Error (OpLoc, NoENDM); /* Premature EOF */ i = 0; break; } if ((i += CountNest (OpCode)) < 0) { Error (OpLoc,ManyENDC); /* Unmatched ENDC */ i = 0; } if (!Pass2) AddName (Line, 2); /* Store a line */ if (strcmp (OpCode, "ENDM") == 0) break; /* Main program echoes ENDM */ if (Pass2) WriteListLine (&List); /* Echo a line */ } if (i > 0) Error (OpLoc, NoENDC); /* ENDC is missing */ break; case IfEQ: /* IFEQ */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc != 0) SkipNest++; /* Skip to the next ENDC */ break; case IfNE: /* IFNE */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc == 0) SkipNest++; break; case IfGT: /* IFGT */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc <= 0) SkipNest++; break; case IfGE: /* IFGE */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc < 0) SkipNest++; break; case IfLT: /* IFLT */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc >= 0) SkipNest++; break; case IfLE: /* IFLE */ ObjSrc = GetValue (SrcOp, SrcLoc); if (ObjSrc > 0) SkipNest++; break; case IfC: /* IFC */ if (strcmp (SrcOp, DestOp) != 0) SkipNest++; break; case IfNC: /* IFNC */ if (strcmp (SrcOp, DestOp) == 0) SkipNest++; break; case IfD: /* IFD */ if (ReadSymTab (SrcOp)) AddRef (LineCount); if (DefLine2 > LineCount) SkipNest++; break; case IfND: /* IFND */ if (ReadSymTab (SrcOp)) AddRef (LineCount); if (DefLine2 <= LineCount) SkipNest++; break; case EndC: /* ENDC */ break; /* LineParts will take care of it */ case Section: /* SECTION */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ tempop[0] = '\0'; s = Line + DestLoc + strlen (DestOp); /* Check for flags */ if (*s == ',') { s++; GetField (s, tempop); /* Get specification */ } DoSection (SrcOp, SrcLoc, DestOp, DestLoc, tempop, j); break; case CSeg: /* CODE */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ DoSection (SrcOp, SrcLoc, "CODE", OpLoc, DestOp, DestLoc); break; /* Treat as SECTION */ case DSeg: /* DATA */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ DoSection (SrcOp, SrcLoc, "DATA", OpLoc, DestOp, DestLoc); break; /* Treat as SECTION */ case BSS: /* BSS */ if (SFormat) Error (OpLoc, NotSFmt); /* Not in S-format */ DoSection (SrcOp, SrcLoc, "BSS", OpLoc, DestOp, DestLoc); break; /* Treat as SECTION */ case Idnt: /* IDNT */ s = Line + SrcLoc; if ((*s == '"') || (*s == '\'')) s++; /* Ignore quotes */ t = IdntName; while (!isspace(*s) && (*s != '"') && (*s != '\'') && (*s != '\0')) *t++ = *s++; *t = '\0'; break; case DCB: /* 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 (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 = MakeHunk = TRUE; break; case Equr: /* 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 */ } break; case Reg: /* REG */ if (Label[0] == '\0') Error (0, NeedLab); /* Need a label */ else { if ((i = GetMultReg (SrcOp, SrcLoc)) == 0) { Error (SrcLoc, OperErr); } else { if (!ReadSymTab (Label)) { /* Make a new entry */ AddSymTab (Label, (long) i, 0L, LineCount, 0x40); GotEqur = TRUE; /* We have at least one EQUR */ } } } break; case Near: /* NEAR */ SmallData = TRUE; /* Set small-data model flag */ AnyNear = TRUE; /* Remember that we use it somewhere */ break; case Far: /* FAR */ SmallData = FALSE; /* Reset small-data model flag */ break; default: break; } return (Dir); } DoSection (name, nameloc, type, typeloc, flags, flagloc) char *name, *type, *flags; int nameloc, typeloc, flagloc; /* Processes SECTION directive or equivalent */ { static long HunkPos; /* Seek address of start of section */ register char *s, *t; long newflags, templong; char tempop[MAXLINE]; PrntAddr = TRUE; for (s = type; *s; s++) /* Convert section type */ *s = toupper (*s); /* to upper case */ if ((type[0] == '\0') || (strcmp (type, "CODE") == 0)) newflags = HunkCode; /* Code section */ else if (strcmp (type, "DATA") == 0) newflags = HunkData; /* Data section */ else if (strcmp (type, "BSS") == 0) newflags = HunkBSS; /* BSS section */ else { Error (typeloc, OperErr); /* Invalid type */ strcpy (type, "CODE"); newflags = HunkCode; /* Make it CODE */ } newflags <<= 16; /* Shift to high-order 16 bits */ if (flags[0]) { for (s = flags; *s; s++) /* Convert flags */ *s = toupper (*s); /* to upper case */ if (strcmp (flags, "CHIP") == 0) newflags |= MEMF_CHIP; /* CHIP memory */ else if (strcmp (flags, "FAST") == 0) newflags |= MEMF_FAST; /* FAST memory */ else Error (flagloc, OperErr); /* Invalid - ignore */ } templong = (newflags & 0xFFFF0000) >> 16; sprintf (tempop," %4x",HunkSeq++); /* Make section name unique */ s = name; if ((*s == '"') || (*s == '\'')) s++; /* Ignore quotes */ t = tempop + 6; while (!isspace(*s) && (*s != '"') && (*s != '\'') && (*s != '\0')) *t++ = *s++; /* Concatenate section name */ *t = '\0'; if (ReadSymTab (tempop)) { /* Scan for section name */ if (HunkType == HunkNone) { SectLine = 1; /* Start of first section */ } else { if (Pass2) { AddRef (LineCount); DumpSdata (&Srec); /* Finish the previous hunk */ if (!MakeHunk) { /* If it was a null hunk, */ if (Srec.Ptr > Srec.Buf) /* overwrite it. */ write (Srec.fd, Srec.Buf, Srec.Ptr - Srec.Buf); lseek (Srec.fd, HunkPos, 0); Srec.Ptr = Srec.Buf; } } else { AddrCnt = AddrBndL (AddrCnt); /* Finish on long word */ } if (AddrCnt > OrgHigh) Sect->Val = AddrCnt; /* End of old section */ else Sect->Val = OrgHigh; /* We've ORGed higher */ SectLine = LineCount; /* Start of new section */ } Sect = Sym; /* Point to new section */ AddrCnt = SectStart = Sym->Val; /* Continuation */ OrgHigh = 0L; OrgFlag = FALSE; 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 */ HunkPos = lseek (Srec.fd, 0L, 1); HunkPos += Srec.Ptr - Srec.Buf; /* It starts here */ templong = HunkName; xputl (&Srec, templong); if (tempop[6]) DumpName (&Srec, &tempop[6], 0L); /* Hunk name */ else DumpName (&Srec, " ", 0L); xputl (&Srec, HunkType); /* Hunk type */ LenPtr = Srec.Ptr; /* Pointer to hunk length */ LenPos = lseek (Srec.fd, 0L, 1); LenPos += LenPtr-Srec.Buf; /* Hunk length goes here */ xputl (&Srec, 0L); /* For now, set it to zero */ } MakeHunk = FALSE; /* We don't have anything yet */ if (AnyNear && (CurrHunk > 1)) Error (OpLoc, ManySect); /* Too many hunks for small data */ return; } AddrCnt = AddrBndL (AddrCnt); /* Finish on long word bounary */ if (Pass2) { Error (OpLoc, ManySect); /* Table overflowed in pass 1 */ return; } if (NextHunk >= ABSHUNK) /* Set up a new table entry */ return; /* Section table overflow */ if (HunkType != HunkNone) { if (AddrCnt > OrgHigh) Sect->Val = AddrCnt; /* End of old section */ else Sect->Val = OrgHigh; /* We've ORGed higher */ SectLine = LineCount; /* Starting line number */ } else { SectLine = 1; /* Start of first section */ } AddrCnt = SectStart = OrgHigh = 0L; /* Reset location counter */ OrgFlag = FALSE; TempAddr = StartAddr = AddrCnt; HunkType = (newflags & 0x3FFF0000L) >> 16; /* Type */ HunkFlags = newflags & 0xC0000000L; /* Flags */ 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 */ MakeHunk = FALSE; /* We don't have anything yet */ if (AnyNear && (CurrHunk > 1)) Error (OpLoc, ManySect); /* Too many hunks for small data */ return; } SHAR_EOF cat << \SHAR_EOF > Codegen.c /*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Object code generator - January 6, 1989 */ /* */ /* 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 1989 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ #include <stdio.h> #include "a68kdef.h" #include "a68kglb.h" /* Functions */ extern int LineParts(), Instructions(), ObjDir(); extern int GetInstModeSize(), GetMultReg(), CountNest(); extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl(); extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue(); extern char *AddName(), *GetField(); extern struct SymTab *NextSym(); extern struct SymTab **HashIt(); GetObjectCode (dummy) int dummy; /* Determines the object code for the operation as well as the operands */ /* Returns each (up to 3 fields), along with the length of each. */ { int quick; int ExtL; /* Bit pattern for instruction extension word */ long templong; char tempop[MAXLINE]; register int i, j; i = Instructions (OpLoc); /* Analyze the opcode */ if (Dir != None) { ObjDir (dummy); /* Process directives */ return; } if ((Label[0] != '\0') || (OpCode[0] != '\0')) PrntAddr = TRUE; /* Print address at least */ if (OpCode[0] == '\0') { MakeHunk |= PrntAddr; return; /* No op code, exit now */ } if (!i) { /* Unrecognized opcode */ if ((Quiet < 0) && (InF->UPtr == 0)) ShowLine (InF->Line); /* Show where we are */ if (OpCode[0] == '*') { Error (OpLoc, NoCode); /* Don't try to open the console! */ return; } if (Size == Byte) /* Set up \0 parameter */ MacSize[0] = 'B'; else if (Size == Long) MacSize[0] = 'L'; else MacSize[0] = 'W'; AddrAdv = InstSize = 0; PrntAddr = FALSE; Dir = MacCall; /* Assume it's a macro call */ if (InF->UPtr == 0) { /* If we're reading from a file */ InF->Pos = lseek (In.fd, 0L,1); /* remember where we are. */ InF->Pos -= In.Lim - In.Ptr; } tempop[0] = ' '; tempop[1] = '\0'; strcat (tempop, OpCode); /* Prepend a blank to OpCode */ if (ReadSymTab (tempop)) { /* Search for user macro */ AddRef (LineCount); if(Sym->Defn < LineCount) { /* Only if previously defined! */ InFNum++; if (--InF < LowInF) LowInF = InF; MacCount++; Heap2Space (0); /* Check for space */ InF->UPtr = (char *) Hunk2; /* MACRO statement */ InF->UPtr += strlen(InF->UPtr) + 1; /* Skip over it */ InF->NPtr = NextFNS; /* New stack pointer */ InF->Line = 0; /* Line number in macro */ InF->NArg=GetArgs (""); /* Get arguments */ InF->MCnt = MacCount; /* Macro number */ if (OuterMac == 0) OuterMac = InFNum; /* Outer macro */ return; } } if (!OpenIncl (OpCode, InclList)) { Error (OpLoc, NoCode); /* Couldn't open file */ Dir = BadMac; /* Invalid macro */ if (InF->UPtr == 0) { In.fd = open (InF->NPtr, 0); lseek (In.fd, InF->Pos, 0); In.Ptr = In.Lim = In.Buf; } return; /* Return to outer file */ } InFNum++; /* Bump nesting level */ if (--InF < LowInF) LowInF = InF; MacCount++; Heap2Space (0); /* Check for space */ InF->UPtr = 0; /* Not a user macro */ InF->NPtr = NextFNS; /* New stack pointer */ InF->Line = 0; /* Line number in macro */ InF->NArg = GetArgs (OpCode); /* Get arguments */ InF->MCnt = MacCount; /* Macro number */ if (OuterMac == 0) OuterMac = InFNum; /* Outer macro */ return; } MakeHunk = TRUE; /* We have something for a hunk */ AddrCnt = AddrBndW (AddrCnt); /* It'll be word-aligned */ if ((AdrModeA != 0) || (AdrModeB != 0)) { Src.Loc = SrcLoc; Dest.Loc = DestLoc; GetOperand (SrcOp, &Src, SrcPC IN AdrModeB ? 2 : 0); GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0); } if (EA05z IN AdrModeB) { /* MOVEM */ if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) { OpCode[4] = '\0'; /* MOVEM of a single register */ Instructions (OpLoc); /* becomes a straight MOVE */ } } if ((Src.Mode == Imm) /* Immediate instructions */ && (Src.Hunk == ABSHUNK) && (Src.Defn < LineCount) && (((EA611 IN AdrModeB) && (Dest.Mode == DReg) /* MOVE */ && (Size == Long) && (Src.Value >= -128) && (Src.Value <= 127)) || ((EA05y IN AdrModeB) /* ADD/SUB */ && (Src.Value > 0) && (Src.Value <= 8)))) { strcat (OpCode, "Q"); /* Make it ADDQ/SUBQ/MOVEQ */ Instructions (OpLoc); } else if ((Dest.Mode == ARDir) && (Src.Mode <= 12) && (((EA05y | EA611) IN AdrModeB) /* ADD, SUB, or MOVE */ || (OpM68C IN AdrModeA))) { /* CMP */ strcat (OpCode, "A"); /* ADD op,An becomes ADDA etc. */ Instructions (OpLoc); } else if ((Src.Mode == Imm) /* Immediate instructions */ && ((OpM68D | OpM68C | OpM68X) IN AdrModeA)) { strcat (OpCode, "I"); /* ADD/AND/OR/SUB, CMP, EOR */ Instructions (OpLoc); /* ADD #op,d becomes ADDI etc. */ } else if ((Src.Mode == ARPost) && (Dest.Mode == ARPost) && (OpM68C IN AdrModeA)) { /* CMP */ strcat (OpCode, "M"); /* Generate CMPM if necessary */ Instructions (OpLoc); } /*=================== Operand validation routines ====================*/ if (Pass2) { /* If an immediate operand isn't absolute, it must be a long word */ if ((Src.Mode == Imm) && (Size != Long) && (Src.Hunk != ABSHUNK)) Error (SrcLoc, RelErr); /* ------- Check for instructions with too many operands. ------- */ /* Some specialized instruction routines contain their own tests. */ if (AdrModeA == 0) { /* Should have only one operand */ if ((AdrModeB == EA05e) || (AdrModeB == (Size67 | EA05e))) { if (Dest.Mode != Null) Error (DestLoc, OperErr); /* } else if (AdrModeB == 0) { */ /* Should have no operands */ /* if (Src.Mode != Null) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); De-activated for now */ } } if ((AdrModeA != 0) || (AdrModeB != 0)) { if(Dest.Mode != NULL) { /* We should never find 3 operands */ j = DestLoc + strlen (DestOp); if ((Line[j] != '\0') && (Line[j] != ';') && (!isspace (Line[j]))) { Error (j, OperErr); } } /* ---------------- Check for missing operands. ----------------- */ if (Src.Mode == Null) { Error (OpLoc+strlen(OpCode), OperErr); /* No source */ } else if (Dest.Mode == Null) { if (((ImmMode & AdrModeB) == ImmMode) || (TwoOpsA IN AdrModeA) || (TwoOpsB IN AdrModeB)) { Error (SrcLoc+strlen(SrcOp), OperErr); /* No dest. */ } } } } /*====================================================================*/ /* ---------------- Decrement and Branch (DBcc) ----------------- */ if (DecBr IN AdrModeA) { if (Pass2) { if (Src.Mode != DReg) Error (SrcLoc, ModeErr); if (Dest.Value & 1) Error (DestLoc, AlignErr); /* Boundary alignment error */ if (Dest.Hunk == CurrHunk) { ObjSrc = Dest.Value-AddrCnt-2; /* Relative branch distance */ Dest.Hunk = ABSHUNK; /* Displacement is absolute */ } else ObjSrc = 0; /* Let the linker worry about it */ if ((ObjSrc > 32767) || (ObjSrc < -32768)) Error (DestLoc,BraErr); /* Too far to branch */ if (Dest.Hunk!=CurrHunk) { /* DBcc to another section */ templong = AddrCnt + 2; /* 16-bit relocatable */ PutRel (templong, Dest.Hunk, 2); } ObjOp = Op | Src.Rn; } AddrAdv = 4; nO = nS = 2; return; } /* ------------ Branch (Bcc, including BRA and BSR) ------------- */ if (Brnch IN AdrModeA) { if (Src.Value & 1) Error (SrcLoc, AlignErr); /* Boundary alignment error */ if (Src.Hunk == CurrHunk) { ObjSrc=Src.Value-AddrCnt-2; /* Relative branch distance */ Src.Hunk = ABSHUNK; /* Displacement is absolute */ if (Size != Byte) { if ((ObjSrc >= -128) && (ObjSrc <= 127) && (ObjSrc != 0)) if (DefLine2 < LineCount) Size = Byte; /* Short branch if possible */ else if (Pass2 && FwdProc && (Size != Byte)) FwdShort=TRUE; /* Fwd. ref. could be made short */ } if ((Size == Byte) && (ObjSrc == 0)) Error (SrcLoc, BccSDsp0); /* Can't do this! */ } else { ObjSrc = 0; /* Let the linker worry about it */ if (Size == Byte) Error (SrcLoc, BraErr); /* No external short branches! */ } if (Size != Byte) { InstSize = 4; nS = 2; templong = 32767; } else { InstSize = 2; Op |= (ObjSrc & 0x00FF); templong = 127; } if ((ObjSrc > templong) || (ObjSrc < -templong-1)) Error (SrcLoc, BraErr); /* Too far to branch */ if (Dest.Mode != Null) Error (DestLoc, OperErr); /* No Destination operand! */ AddrAdv = InstSize; ObjOp = Op; nO = 2; if (Src.Hunk != CurrHunk) { /* Bcc to another section */ templong = AddrCnt + 2; /* 16-bit relocatable */ PutRel (templong, Src.Hunk, 2); } return; } /* ------------ Check for short (16-bit) JMP or JSR ------------- */ if ((Op == JMP) || (Op == JSR)) if ((Size == Byte) && (Src.Mode == AbsL)) Src.Mode = AbsW; /* Uses information from Instructions & GetOperand (among others) */ /* to complete calculation of Object Code. */ /* Op, AdrModeA, AdrModeB, Size, and Src & Dest records are all */ /* Global variables imported from the SyntaxAnalyzer MODULE. */ ExtL = 0; quick = FALSE; /* ------------ Check for boundary alignment errors. ------------ */ /* BCHG, BCLR, BSET, BTST, LEA, NBCD, PEA, Scc, TAS are exempt. */ if (Pass2) { if ((Size != Byte) && (Op != LEA) && (Op != PEA) && !((AdrModeA == 0) && (AdrModeB == 0)) && !(AdrModeB & EA05c) /* BTST */ && !((AdrModeB&EA05e) && (AdrModeA==0) && !(AdrModeB&Size67))) { if (Src.Value & 1) if ((Src.Mode >= ARDisp) && (Src.Mode <= PCDisX)) Error (SrcLoc, AlignErr); if (Dest.Value & 1) if ((Dest.Mode >= ARDisp) && (Dest.Mode <= PCDisX)) Error (DestLoc, AlignErr); } /* Check for 5 special cases first */ if (Op == STOP) { if (Src.Mode != Imm) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } if (Op == LINK) { Op |= Src.Rn; if (Src.Mode != ARDir) Error (SrcLoc, ModeErr); if (Dest.Mode != Imm) Error (DestLoc, ModeErr); else if (Dest.Value & 1) Error (DestLoc, AlignErr); /* Boundary alignment error */ } if (Op == SWAP) { if (!(EA05f IN AdrModeB)) { /* Ignore if PEA instruction */ Op |= Src.Rn; if (Src.Mode != DReg) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } } if (Op == UNLK) { Op |= Src.Rn; if (Src.Mode != ARDir) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } /* Now do generalized address modes */ if ((Ry02 IN AdrModeA)&&(Rx911 IN AdrModeA)) { /* 2 registers */ if (Op == CMPM) { /* Special routine for CMPM */ Op |= Src.Rn | (Dest.Rn << 9); if (Src.Mode != ARPost) Error (SrcLoc, ModeErr); if (Dest.Mode != ARPost) Error (DestLoc, ModeErr); } else { /* Other two-register instructions */ Op |= Src.Rn | (Dest.Rn << 9); if (RegMem3 IN AdrModeA) { if (Src.Mode == DReg) { if (Dest.Mode != DReg) Error (DestLoc, ModeErr); } else if (Src.Mode == ARPre) { Op |= 0x0008; if (Dest.Mode != ARPre) Error (DestLoc, ModeErr); } else Error (SrcLoc, OperErr); } else { if (Src.Mode == ARPost) if (Dest.Mode != ARPost) Error (DestLoc, ModeErr); else Error (SrcLoc, OperErr); } } } } if (Data911 IN AdrModeA) { /* Data in 9-11 (ADDQ/SUBQ) */ quick = TRUE; if (Src.Mode == Imm) if ((Src.Value > 0) && (Src.Value <= 8)) { if (Src.Value < 8) /* Data of 8 is coded as 000 */ Op |= Src.Value << 9; } else Error (SrcLoc, SizeErr); else Error (SrcLoc, OperErr); } if (CntR911 IN AdrModeA) { /* Only Shift/Rotate use this */ if (Dest.Mode == DReg) { Op = (Op & 0xF9FF) | Dest.Rn; if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; if (Src.Mode == DReg) Op |= 0x0020 | (Src.Rn << 9); else if (Src.Mode == Imm) { quick = TRUE; /* Range Check */ if ((Src.Value > 0) && (Src.Value <= 8)) { if (Src.Value < 8) /* Data of 8 is coded as 000 */ Op |= (Src.Value << 9); } else Error (SrcLoc, SizeErr); } else Error (SrcLoc, OperErr); } else if (Dest.Mode == Null) { Op = (Op & 0xFFE7) | 0x00C0; EffAdr (&Src, (mea | aea)); } else Error (SrcLoc, OperErr); } if (Data03 IN AdrModeA) { /* TRAP Vector in 0-3 */ quick = TRUE; if (Src.Mode == Imm) if ((Src.Value >= 0) && (Src.Value < 16)) Op |= Src.Value; else Error (SrcLoc, SizeErr); else Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } if (Data07 IN AdrModeA) { /* Data in 0-7 (MOVEQ) */ quick = TRUE; Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9); if (Src.Mode != Imm) Error (SrcLoc, ModeErr); else if (Dest.Mode != DReg) Error (DestLoc, ModeErr); else if ((Src.Value < -128) || (Src.Value > 127)) Error (SrcLoc, SizeErr); } if (Pass2) { if (OpM68D IN AdrModeA) { /* DReg in 6-8 (ADD/AND/OR/SUB) */ if (Dest.Mode == DReg) { Op |= (Dest.Rn << 9); if ((Src.Mode == ARDir) && (Size == Byte)) Error (SrcLoc, SizeErr); } else /* Assume Src.Mode = DReg -- Error trapped elsewhere */ Op |= (Src.Rn << 9) | 0x0100; if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; } if (OpM68A IN AdrModeA) { /* AReg in 6-8 (ADDA/CMPA/SUBA) */ if (Dest.Mode == ARDir) Op |= (Dest.Rn << 9); else Error (DestLoc, ModeErr); if (Size == Byte) Error (OpLoc+5, SizeErr); if (Size == Word) Op |= 0x00C0; if (Size == Long) Op |= 0x01C0; } if (OpM68C IN AdrModeA) { /* CMP (Compare) */ if (Dest.Mode == DReg) Op |= (Dest.Rn << 9); else Error (DestLoc, ModeErr); if (Size == Byte) { if (Src.Mode == ARDir) Error (OpLoc+4, SizeErr); } if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; } if (OpM68X IN AdrModeA) { /* EOR (Exclusive or) */ if (Src.Mode == DReg) Op |= (Src.Rn << 9); else Error (SrcLoc, ModeErr); if (Size == Byte) Op |= 0x0100; if (Size == Word) Op |= 0x0140; if (Size == Long) Op |= 0x0180; } if (OpM68S IN AdrModeA) { /* EXT (Sign extension) */ if (Src.Mode == DReg) Op |= Src.Rn; else Error (SrcLoc, ModeErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); if (Size == Byte) Error (OpLoc+4, SizeErr); if (Size == Word) Op |= 0x0080; if (Size == Long) Op |= 0x00C0; } if (OpM68R IN AdrModeA) { /* MOVEP (Register/memory) */ if ((Src.Mode == DReg) && (Dest.Mode == ARDisp)) { if (Size == Byte) Error (OpLoc+6, SizeErr); if (Size == Word) Op |= 0x0180; if (Size == Long) Op |= 0x01C0; Op |= (Src.Rn << 9) | Dest.Rn; } else if ((Src.Mode == ARDisp) && (Dest.Mode == DReg)) { if (Size == Byte) Error (OpLoc+6, SizeErr); if (Size == Word) Op |= 0x0100; if (Size == Long) Op |= 0x0140; Op |= Src.Rn | (Dest.Rn << 9); } else Error (SrcLoc, ModeErr); } if (OpM37 IN AdrModeA) { /* EXG (Exchange registers) */ if ((Src.Mode == DReg) && (Dest.Mode == DReg)) Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn; else if ((Src.Mode == ARDir) && (Dest.Mode == ARDir)) Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn; else if ((Src.Mode == ARDir) && (Dest.Mode == DReg)) Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn; else if ((Src.Mode == DReg) && (Dest.Mode == ARDir)) Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn; else Error (SrcLoc, ModeErr); } if (Bit811 IN AdrModeB) { /* Bit operations using bits 8-11 */ Size = Word; /* Ignore size specification */ if (Src.Mode == DReg) Op |= 0x0100 | (Src.Rn << 9); else if (Src.Mode == Imm) Op |= 0x0800; else Error (SrcLoc, ModeErr); } if (Size67 IN AdrModeB) { /* Size in bits 6-7 */ /* if (Size == Byte) ; No action -- bits are already 0 */ if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; } if (Size6 IN AdrModeB) { /* Size in bit 6 (MOVEM) */ if (Size == Byte) Error (OpLoc+6, SizeErr); /* if (Size == Word) ; No Action -- bit is already 0 */ if (Size == Long) Op |= 0x0040; } if (Sz1213A IN AdrModeB) { /* Size in 12-13 (MOVE) */ if (Size == Byte) Op |= 0x1000; if (Size == Word) Op |= 0x3000; if (Size == Long) Op |= 0x2000; } if (Sz1213 IN AdrModeB) { /* Size in 12-13 (MOVEA) */ if (Dest.Mode == DReg) /* Can't be to data register! */ Error(DestLoc,ModeErr); /* (Others are caught elsewhere) */ Op |= (Dest.Rn << 9); if (Size == Byte) Error (OpLoc+6, SizeErr); if (Size == Word) Op |= 0x3000; if (Size == Long) Op |= 0x2000; } if (EA05a IN AdrModeB) /* Effective address - all */ if ((Dest.Mode == DReg) || (Dest.Mode == ARDir)) EffAdr (&Src, ea); else Error (DestLoc, ModeErr); if (EA05b IN AdrModeB) /* Eff. Addr. - all except ARDir */ if (Dest.Mode == DReg) { EffAdr (&Src, dea); Op |= (Dest.Rn << 9); } else Error (DestLoc, ModeErr); if (EA05c IN AdrModeB) /* BTST */ EffAdr (&Dest, 0x0802); /* All but ARDir/Imm */ if(EA05d IN AdrModeB) { /* All but PC relative & immediate */ EffAdr (&Dest, aea); if ((Dest.Mode == ARDir) && (Size == Byte)) Error (OpLoc+5, SizeErr); } if(EA05e IN AdrModeB) { /* All but ARDir, PC relative, Imm */ if (Dest.Mode == Null) EffAdr (&Src, (dea | aea)); else if ((Src.Mode == Imm) || (Src.Mode == DReg)) EffAdr (&Dest, (dea | aea)); else Error (SrcLoc, ModeErr); } if (EA05f IN AdrModeB) { /* JMP, JSR, LEA, and PEA */ EffAdr (&Src, cea); if (Rx911 IN AdrModeA) if (Dest.Mode == ARDir) Op |= (Dest.Rn << 9); /* Address Reg. for LEA */ else Error(DestLoc,ModeErr); /* Must load Address Reg. */ else if (Dest.Mode != Null) Error (DestLoc, OperErr); /* No Dest. unless LEA */ } if (EA05x IN AdrModeB) { /* AND and OR */ if (Dest.Mode == DReg) EffAdr (&Src, dea); else if (Src.Mode == DReg) EffAdr (&Dest, mea | aea); else Error (SrcLoc, OperErr); } if (EA05y IN AdrModeB) { /* ADD and SUB */ if (Dest.Mode == DReg) { EffAdr (&Src, ea); if ((Src.Mode == ARDir) && (Size == Byte)) Error (OpLoc+4, SizeErr); } else if (Src.Mode == DReg) EffAdr (&Dest, (mea | aea)); else Error (SrcLoc, ModeErr); } } if (EA05z IN AdrModeB) { /* MOVEM */ if (Pass2) { if (Src.Mode == MultiM) { /* Move to memory */ EffAdr (&Dest, (mea | aea | 0x0008)); ExtL = Src.Value; i = (Dest.Mode == ARPre); /* ExtL flip indicator */ } else if (Dest.Mode == MultiM) { /* Move from memory */ Op |= 0x0400; /* Set direction */ EffAdr (&Src, (mea | 0x0810)); ExtL = Dest.Value; i = (Src.Mode == ARPre); } else { Error (SrcLoc, OperErr); i = FALSE; } if (i) { /* Flip ExtL if ARPre */ j = 0; for (i = 0; i < 8; i++) j |= (ExtL & (1<<i)) << (15-i*2); for (i = 8; i < 16; i++) j |= (ExtL & (1<<i)) >> (i*2-15); ExtL = j; } } nO += 2; /* Extension is part of OpCode */ InstSize += 2; } if (Pass2) { if (EA611 IN AdrModeB) { /* Eff. Addr. in 6-11 (MOVE) */ if (Dest.Mode == CCR) { /* MOVE to CCR */ Op = 0x44C0; EffAdr (&Src, dea); } else if (Dest.Mode == SR) { /* MOVE to SR */ Op = 0x46C0; EffAdr (&Src, dea); } else if (Src.Mode == SR) { /* MOVE from SR */ Op = 0x40C0; EffAdr (&Dest, dea | aea); } else if (Dest.Mode == USP) { /* MOVE to USP */ Op = 0x4E60; if (Src.Mode == ARDir) Op |= Src.Rn; else Error (SrcLoc, ModeErr); } else if (Src.Mode == USP) { /* MOVE from USP */ Op = 0x4E68; if (Dest.Mode == ARDir) Op |= Dest.Rn; else Error (DestLoc, ModeErr); } else { /* General MOVE instruction */ EffAdr (&Src, (ea | xxx)); if ((Size == Byte) && (Src.Mode == ARDir)) Error (SrcLoc, SizeErr); if (Src.Mode > 12) Error (SrcLoc, ModeErr); if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12)) Error (DestLoc, ModeErr); else if (Dest.Mode < 8) /* Register direct or indirect */ Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn << 9); else /* Absolute, PC relative, or immediate */ Op |= 0x01C0 | ((Dest.Mode - 8) << 9); OperExt (&Dest); /* Set up extension word */ } } if ((Dest.Mode == CCR) && (Src.Mode == Imm)) { if ((Size67 IN AdrModeB) && (EA05e IN AdrModeB) && (Exten IN AdrModeB)) if (0x0400 IN Op) /* not ANDI/EORI/ORI */ Error (DestLoc, ModeErr); else Op = (Op & 0xFF00) | 0x003C; } if ((Dest.Mode == SR) && (Src.Mode == Imm)) { if ((Size67 IN AdrModeB) && (EA05e IN AdrModeB) && (Exten IN AdrModeB)) if (0x0400 IN Op) /* not ANDI/EORI/ORI */ Error (DestLoc, ModeErr); else Op = (Op & 0xFF00) | 0x007C; } } ObjOp = Op; InstSize += 2; nO += 2; if (nO > 2) { templong = ExtL; /* Add extension word */ ObjOp = (ObjOp << 16) | (templong & 0x0000FFFFL); } if ((AdrModeA != 0) || (AdrModeB != 0)) { InstSize += (nS = GetInstModeSize (Src.Mode)); ObjSrc = Src.Value; InstSize += (nD = GetInstModeSize (Dest.Mode)); ObjDest = Dest.Value; } if (quick) { InstSize -= nS; /* Source operand is in Op */ nS = 0; } if (Pass2) { if ((nS!=0) && (Src.Hunk!=ABSHUNK)) { /* SrcOp relocatable */ if ((Src.Mode == AbsL) || (Src.Mode == AbsW) || (Src.Mode == ARDisp) || (Src.Mode == PCDisp) || (Src.Mode == Imm)) { templong = AddrCnt+nO; /* 32- or 16-bit relocatable */ PutRel (templong, Src.Hunk, nS); } if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) { templong = AddrCnt + nO + 1; /* 8-bit relocatable */ PutRel (templong, Src.Hunk, 1); } } if ((nD!=0) && (Dest.Hunk!=ABSHUNK)) { /* DestOp relocatable */ if ((Dest.Mode == AbsL) || (Dest.Mode == AbsW) || (Dest.Mode == ARDisp) || (Dest.Mode == PCDisp) || (Dest.Mode == Imm)) { templong = AddrCnt+nO+nS; /* 32- or 16-bit relocatable */ PutRel (templong, Dest.Hunk, nD); } if ((Dest.Mode==ARDisX) || (Dest.Mode==PCDisX)) { templong = AddrCnt+nO+nS+1; /* 8-bit relocatable */ PutRel (templong, Dest.Hunk, 1); } } } AddrAdv = InstSize; } SHAR_EOF cat << \SHAR_EOF > Opcodes.c /*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Opcode table and scan routine - January 6, 1989 */ /* */ /* 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 1989 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ #include <stdio.h> #include "a68kdef.h" #include "a68kglb.h" /* Functions */ extern int LineParts(), ObjDir(); extern int GetInstModeSize(), GetMultReg(), CountNest(); extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl(); extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue(); extern char *AddName(), *GetField(); extern struct SymTab *NextSym(); extern struct SymTab **HashIt(); int Instructions (loc) int loc; /* Looks up opcode and addressing mode bit patterns If the opcode corresponds to an executable instruction, returns TRUE with the following fields set up: Op - operation code bits AdrModeA - addressing mode bits AdrModeB - more addressing mode bits Dir - None If the opcode corresponds to a directive (AdrModeA in the table is 0xFFFF), returns TRUE with the following fields set up: Op - 0 AdrModeA - 0 AdrModeB - 0 Dir - the appropriate directive value If not found, returns FALSE with all the above fields set to zero. NOTE: The binary search doesn't use strcmp because this function returns incorrect values under MS-DOS Lattice 2.12. */ { static int maxinst = 0; /* Size of opcode table */ static int limits['Z'-'A'+2]; /* Table limits by first letter */ register char *i, *j; register int lower, upper, mid; /* Binary search controls */ /* Opcode table */ struct OpTab { char Mnem[8]; /* Instruction mnemonic */ int OpBits; /* Op code bits */ int AMA; /* Address mode bits */ int AMB; /* More address mode bits */ }; static struct OpTab MnemTab[] = { "=", 0, 0xFFFF, Equ, "ABCD", 0xC100, Rx911 | RegMem3 | Ry02, 0, "ADD", 0xD000, OpM68D, EA05y, "ADDA", 0xD000, OpM68A, EA05a, "ADDI", 0x0600, 0, Size67 | EA05e | Exten, "ADDQ", 0x5000, Data911, Size67 | EA05d, "ADDX", 0xD100, Rx911 | RegMem3 | Ry02, Size67, "AND", 0xC000, OpM68D, EA05x, "ANDI", 0x0200, 0, Size67 | EA05e | Exten, "ASL", 0xE100, CntR911, 0, "ASR", 0xE000, CntR911, 0, "BCC", 0x6400, Brnch, 0, "BCHG", 0x0040, 0, EA05e | Exten | Bit811, "BCLR", 0x0080, 0, EA05e | Exten | Bit811, "BCS", 0x6500, Brnch, 0, "BEQ", 0x6700, Brnch, 0, "BGE", 0x6C00, Brnch, 0, "BGT", 0x6E00, Brnch, 0, "BHI", 0x6200, Brnch, 0, "BLE", 0x6F00, Brnch, 0, "BLS", 0x6300, Brnch, 0, "BLT", 0x6D00, Brnch, 0, "BMI", 0x6B00, Brnch, 0, "BNE", 0x6600, Brnch, 0, "BPL", 0x6A00, Brnch, 0, "BRA", 0x6000, Brnch, 0, "BSET", 0x00C0, 0, EA05e | Exten | Bit811, "BSR", 0x6100, Brnch, 0, "BSS", 0, 0xFFFF, BSS, "BTST", 0x0000, 0, EA05c | Exten | Bit811, "BVC", 0x6800, Brnch, 0, "BVS", 0x6900, Brnch, 0, "CHK", 0x4180, Rx911, EA05b, "CLR", 0x4200, 0, Size67 | EA05e, "CMP", 0xB000, OpM68C, EA05a, "CMPA", 0xB000, OpM68A, EA05a, "CMPI", 0x0C00, 0, Size67 | EA05e | Exten, "CMPM", 0xB108, Rx911 | Ry02, Size67, "CNOP", 0, 0xFFFF, Cnop, "CODE", 0, 0xFFFF, CSeg, "CSEG", 0, 0xFFFF, CSeg, "DATA", 0, 0xFFFF, DSeg, "DBCC", 0x54C8, DecBr, 0, "DBCS", 0x55C8, DecBr, 0, "DBEQ", 0x57C8, DecBr, 0, "DBF", 0x51C8, DecBr, 0, "DBGE", 0x5CC8, DecBr, 0, "DBGT", 0x5EC8, DecBr, 0, "DBHI", 0x52C8, DecBr, 0, "DBLE", 0x5FC8, DecBr, 0, "DBLS", 0x53C8, DecBr, 0, "DBLT", 0x5DC8, DecBr, 0, "DBMI", 0x5BC8, DecBr, 0, "DBNE", 0x56C8, DecBr, 0, "DBPL", 0x5AC8, DecBr, 0, "DBRA", 0x51C8, DecBr, 0, "DBT", 0x50C8, DecBr, 0, "DBVC", 0x58C8, DecBr, 0, "DBVS", 0x59C8, DecBr, 0, "DC", 0, 0xFFFF, DC, "DCB", 0, 0xFFFF, DCB, "DIVS", 0x81C0, Rx911, EA05b, "DIVU", 0x80C0, Rx911, EA05b, "DS", 0, 0xFFFF, DS, "DSEG", 0, 0xFFFF, DSeg, "END", 0, 0xFFFF, End, "ENDC", 0, 0xFFFF, EndC, "ENDIF", 0, 0xFFFF, EndC, "EOR", 0xB000, OpM68X, EA05e, "EORI", 0x0A00, 0, Size67 | EA05e | Exten, "EQU", 0, 0xFFFF, Equ, "EQUR", 0, 0xFFFF, Equr, "EVEN", 0, 0xFFFF, Even, "EXG", 0xC100, OpM37, 0, "EXT", 0x4800, OpM68S, 0, "FAR", 0, 0xFFFF, Far, "IDNT", 0, 0xFFFF, Idnt, "IFC", 0, 0xFFFF, IfC, "IFD", 0, 0xFFFF, IfD, "IFEQ", 0, 0xFFFF, IfEQ, "IFGE", 0, 0xFFFF, IfGE, "IFGT", 0, 0xFFFF, IfGT, "IFLE", 0, 0xFFFF, IfLE, "IFLT", 0, 0xFFFF, IfLT, "IFNC", 0, 0xFFFF, IfNC, "IFND", 0, 0xFFFF, IfND, "IFNE", 0, 0xFFFF, IfNE, "ILLEGAL", 0x4AFC, 0, 0, "INCLUDE", 0, 0xFFFF, Include, "JMP", 0x4EC0, 0, EA05f, "JSR", 0x4E80, 0, EA05f, "LEA", 0x41C0, Rx911, EA05f, "LINK", 0x4E50, Ry02, Exten, "LIST", 0, 0xFFFF, DoList, "LSL", 0xE308, CntR911, 0, "LSR", 0xE208, CntR911, 0, "MACRO", 0, 0xFFFF, Macro, "MOVE", 0x0000, 0, Sz1213A | EA611, "MOVEA", 0x0040, Rx911, Sz1213 | EA05a, "MOVEM", 0x4880, 0, Size6 | EA05z | Exten, "MOVEP", 0x0008, OpM68R, Exten, "MOVEQ", 0x7000, Data07, 0, "MULS", 0xC1C0, Rx911, EA05b, "MULU", 0xC0C0, Rx911, EA05b, "NBCD", 0x4800, 0, EA05e, "NEAR", 0, 0xFFFF, Near, "NEG", 0x4400, 0, Size67 | EA05e, "NEGX", 0x4000, 0, Size67 | EA05e, "NOL", 0, 0xFFFF, NoList, "NOLIST",0, 0xFFFF, NoList, "NOP", 0x4E71, 0, 0, "NOT", 0x4600, 0, Size67 | EA05e, "OR", 0x8000, OpM68D, EA05x, "ORG", 0, 0xFFFF, Org, "ORI", 0x0000, 0, Size67 | EA05e | Exten, "PAGE", 0, 0xFFFF, Page, "PEA", 0x4840, 0, EA05f, "PUBLIC",0, 0xFFFF, Public, "REG", 0, 0xFFFF, Reg, "RESET", 0x4E70, 0, 0, "ROL", 0xE718, CntR911, 0, "ROR", 0xE618, CntR911, 0, "RORG", 0, 0xFFFF, Org, "ROXL", 0xE510, CntR911, 0, "ROXR", 0xE410, CntR911, 0, "RTE", 0x4E73, 0, 0, "RTR", 0x4E77, 0, 0, "RTS", 0x4E75, 0, 0, "SBCD", 0x8100, Rx911 | RegMem3 | Ry02, 0, "SCC", 0x54C0, 0, EA05e, "SCS", 0x55C0, 0, EA05e, "SECTION", 0, 0xFFFF, Section, "SEQ", 0x57C0, 0, EA05e, "SET", 0, 0xFFFF, Set, "SF", 0x51C0, 0, EA05e, "SGE", 0x5CC0, 0, EA05e, "SGT", 0x5EC0, 0, EA05e, "SHI", 0x52C0, 0, EA05e, "SLE", 0x5FC0, 0, EA05e, "SLS", 0x53C0, 0, EA05e, "SLT", 0x5DC0, 0, EA05e, "SMI", 0x5BC0, 0, EA05e, "SNE", 0x56C0, 0, EA05e, "SPC", 0, 0xFFFF, Space, "SPL", 0x5AC0, 0, EA05e, "ST", 0x50C0, 0, EA05e, "STOP", 0x4E72, 0, Exten, "SUB", 0x9000, OpM68D, EA05y, "SUBA", 0x9000, OpM68A, EA05a, "SUBI", 0x0400, 0, Size67 | EA05e | Exten, "SUBQ", 0x5100, Data911, Size67 | EA05d, "SUBX", 0x9100, Rx911 | RegMem3 | Ry02, Size67, "SVC", 0x58C0, 0, EA05e, "SVS", 0x59C0, 0, EA05e, "SWAP", 0x4840, Ry02, 0, "TAS", 0x4AC0, 0, EA05e, "TITLE", 0, 0xFFFF, Title, "TRAP", 0x4E40, Data03, 0, "TRAPV", 0x4E76, 0, 0, "TST", 0x4A00, 0, Size67 | EA05e, "UNLK", 0x4E58, Ry02, 0, "XDEF", 0, 0xFFFF, Xdef, "XREF", 0, 0xFFFF, Xref, "",0,0,0}; /* End-of-table flag */ if (maxinst == 0) { /* Determine size of opcode table */ while (MnemTab[maxinst].Mnem[0]) maxinst++; limits[0] = 0; limits['Z'-'A'+1] = maxinst; mid = 0; for (lower = 0; lower < maxinst; lower++) { upper = (unsigned int) MnemTab[lower].Mnem[0] - 'A' + 1; if (upper != mid) { if (upper > 0) { /* Start of the next letter */ mid++; while (mid < upper) limits[mid++] = lower; limits[mid] = lower; } } } mid++; while (mid < 'Z'-'A'+1) { limits[mid++] = maxinst; /* In case we didn't get to Z */ } } mid = (unsigned int) OpCode[0] - 'A' + 1; if (mid < 0) { /* This catches stuff like "=" */ lower = 0; upper = limits[1]; } else if (mid > 'Z'-'A'+1) { lower = upper = 0; /* Reject this one */ } else { lower = limits[mid++]; upper = limits[mid]; } while (lower < upper) { mid = (lower + upper) / 2; /* Search opcode table */ for (i = OpCode, j = MnemTab[mid].Mnem; *i == *j; i++, j++) if (*i == '\0') break; /* Find first non-match */ if (*i < *j) upper = mid; /* Search lower half of table */ else if (*i > *j) lower = mid + 1; /* Search upper half of table */ else if (MnemTab[mid].AMA != 0xFFFF) { /* Found it */ Op = MnemTab[mid].OpBits; /* Executable instruction */ AdrModeA = MnemTab[mid].AMA; AdrModeB = MnemTab[mid].AMB; Dir = None; return (TRUE); } else { Op = AdrModeA = AdrModeB = 0; /* Directive */ Dir = MnemTab[mid].AMB; return (TRUE); } } Op = AdrModeA = AdrModeB = Dir = 0; return (FALSE); /* Didn't find it */ } SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.