[comp.sources.amiga] v89i025: a68k - 68000 assembler v2.42, Part03/04

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.