; GWASS_ASM on H90
; and win1_ass
; 
; 20th March 1998
;
; $Log$
;
;  An ASSEMBLER program
; for the MC68000 series
;
;  NB This program can only be run
;      on a 68020 or above.
;
	ERR
	DATA	22000
;
LK	MACRO
	IF	\1<\2
	IF	\1=1
	LINK.W	A6,#-60-2
	ELSE
	LINK.W	A6,#-PAR_SZE-2*\1-6
	ENDIF
	BRA.W	PR31_1
	LK	|\1+1~,\2
	ENDIF
	ENDM
;
MSG	MACRO
\4\1	DC.W	\4\1E-\4\1-2
	DC.B	\2\3	(allow up to 64 characters)
\4\1E	DS.B	0
	ENDM
;
G_LST	MACRO
\1
	G_LST1 \1,\2,\3,\4
	ENDM
;
G_LST1	MACRO
	IF \3<=|\4~
	DC.W	\2\3-\1
	G_LST1	\1,\2,|\3+1~,\4
	ENDIF
	ENDM
;
EXTU	MACRO
	IF	1+\4-\3>30
	\5 	\1,\2,\3,|\3+30~
	EXTU	\1,\2,|\3+31~,\4,\5
	ELSE
	\5	\1,\2,\3,\4
	ENDIF
	ENDM
;
ext1	macro
	if	\3<=\4
	dc.w 	\1\3-\2
	ext1	\1,\2,|\3+1~,\4
	endif
	endm
;
TITLE	EQU	?"GW45"
WHITE	EQU	7
BLACK	EQU	0
GREEN	EQU	4
RED	EQU	2
STK_SIZE	EQU	322       20 parameters 2|14 + word no of pars
VAL	EQU	2
TYPE	EQU	6
VERSION	EQU	?"3.32"
VNUM	EQU	?"60"
NO_SEPS	EQU	13        No of separator tests
;
	RSSET	0
EQB	RS.L	1	**************************
EQU_LEN	RS.L	1	*     Dynamic Storage    *
EQU_INC	RS.L	1	*                        *
CH_LST	RS.L	1	*    Space is allotted   *
CH_LENG	RS.L	1	*   in blocks of length  *
CH_INC	RS.L	1	*       x_INC + 1        *
CHM_LST	RS.L	1	*                        *
CHM_LEN	RS.L	1	*   The space allotted   *
CHM_INC	RS.L	1	*  at any time is given  *
IF_ON	RS.L	1	*       in x_LEN         *
IF_LEN	RS.L	1	*                        *
IF_INC	RS.L	1	* When space is allotted *
XREF_IX	RS.L	1	*  the old contents are  *
IX_LEN	RS.L	1	*  copied to it possibly *
IX_INC	RS.L	1	*    with 'relocation'   *
XREF_LST	RS.L	1	* (See EXTENS in 5_ASM)  *
XLST_LEN	RS.L	1	*                        *
XLST_INC	RS.L	1	**************************
BINS	RS.L	1 current chunk
BIN_F	RS.L	1 1st chunk
BIN_L	RS.L	1 last chunk
BLSTCK	EQU	EQB
ER_LST	RS.L	1
TER_LST	RS.L	1
BLLAB	RS.L	1
LINE_NO	RS.L	1
BLLAB1	RS.L	1
STACK	RS.L	1
BIN_BUF	RS.L	1
TMP_BUF	RS.L	1
MOD_NME	RS.B	42
PROMPT	RS.W	1
FILE	RS.B	40
OBUF	RS.L	6
O_BUF	RS.L	101
BUF	RS.W	129
LBUF	RS.L	64
EX_BUF	RS.W	129	for MACRO functions (#LEN etc)
CO_SE	RS.B	32*8	one byte for each SECTION (0='S' 1='C' 2='O')
ID_CON	RS.L	1
CH_IN	RS.L	1	Start of Temporary Buffer
CH_OUT	RS.L	1
CH_PRNT	RS.L	1
CH_TMP	RS.L	1
CH_SYM	RS.L	1
CH_OUT1	RS.L	1
CH_NO	RS.W	1
CHM_NO	RS.W	1
PCK	RS.W	1
PWID	RS.W	1
FLTYP	RS.W	1	allows choice of file type
MAC_NO	RS.W	1
XREF_NO	RS.W	1
SEC_NO	RS.W	1
MAC_CT	RS.W	1
MAC_LST	RS.L	3
SEC_LST	RS.L	3
LAB_LST	RS.L	3
MINN	RS.L	3     "     three info. chunks
SINN	RS.L	3     "     three     "
LINN	RS.L	4     "     four      "
SL1	RS.W	1  label no after EQU_SYM in 1st strand
SL2	RS.W	1      "         "           2nd   "
SL3	RS.W	1      "         "           3rd   "
SEC_PC	RS.L	256
BIN_LINE	RS.L	1   address of allocation in user heap
COMP_MARK	RS.W	1
MAC_BUF	RS.L	64
P_MAC	RS.L	1	pointer to chain of addesses for 'P' file info
BIN_IN	RS.L	1
BIN_OUT	RS.L	1
HEAPAD	RS.L	1
DPCW	RS.L	1
DATA	RS.L	1
ER_SPACE	RS.L	3004      space for errors | KEEP THESE |
CRT_SEC	RS.W	1                          | TOGETHER   |
PC_TOT	RS.L	1      End of Temporary Buffer
PC_INST	RS.L	1
SIZE	RS.W	1
MARK	RS.W	2
EXTBUF	RS.W	7
TMP_NME	RS.L	10
BIN_NME	RS.L	10
REL_NME	RS.L	10
ITEM	RS.L	1
EA_INSMK	RS.L	1
EA_INSMK1	RS.L	1
IF_LNO	RS.L	1
B_FLS	RS.L	1
BF_ADDR	RS.L	1
EA_STK	RS.L	3
;         4 bytes here for -1 entry to PCW
PCW	RS.L	64
SEC_EQLST	RS.L	64	to allow 256 sections
TK2_BUFFER	RS.B	58 to allow paths to filenames
DATAD	RS.B	58	space for DATAD$
PROGD	RS.B	58	space for PROGD$
RS	RS.L	1
G_LIMIT	RS.L	1   lowest STACK address for GLABx
PC_TH	RS.L	1   address of current 6-byte PC list entry
PC_PR	RS.L	1     "        previous  "         "
PC_CS	RS.L	1     "        start of current PC chunk
PC_CS1	RS.L	1     "        start of 1st PC chunk
X_ALLOC1	RS.L	1     "        ALCHP chain
TEMR_L	RS.L	1   For errors in PASS2 - space ALLOC'd then
NO_ERRS	RS.L	1
NO_WARNS	RS.L	1
PC_NOW	RS.L	1
IF_L	RS.W	1
ACT_L	RS.W	1
E_COM	RS.W	1
CPC	EQU	IF_L
TOT_BERRS	RS.L	1   ***************************
DEFAULT	RS.W	1   *          DIP            *
BIN_SWTCH	RS.B	1   * Bit  On        Off      *
CMP_TYPE	RS.B	1   *                         *
REL_SWTCH	RS.B	1   *  0   CASE_DIFF CASE_IND *
DIP	RS.B	1   *  4   LOW_EA    HIGH_EA  *
F_EA	RS.B	1   *  5   ERR       LST      *
ER_EA	RS.B	1   *                         *
B_CNST	RS.B	1   * Bits 1-3  Meaning       *
BATCH	RS.B	1   *  0        68040         *
;		    *  1        68030         *
;		    *  2        68EC030       *
IF_SW	RS.B	1   *  3        68851         *
TEMP_ON	RS.B	1   ***************************
BF	RS.B	1	set 1 for later BATCH
ORG_H	RS.B	1	1=ORG 0=no ORG
;
DEND	EQU	ORG_H+1	end of DATA SPACE
TEMP_BUF	EQU	CH_IN     (up to 4742 bytes @ start)
O_BEND	EQU	BUF
TMACLST	EQU	MAC_BUF
T_BUFSIZE	EQU	4740
HEAP_SIZE	EQU	$15000
MAX_FLES	EQU	677
MAX_SEC	EQU	256
MAX_EQU	EQU	$B000     largest allowable EQU_SYM file
MAX_D	EQU	1023	maximum defaults which can be set
B_BUFSZE	EQU	506
T_BUFSZE	EQU	502
EQU_INC_S	EQU	16-1
BIN_INC_S	EQU	$FE8     406*10 + 12
;
; BINS are chained
;    _____________________________________________________
;    | pointer  | pointer | pointer |< INS >< INS > ..    |
;    ¾          ¾         ¾                       ¾
;    |          |         to first free space ___/
;    |          to previous chunk (or 0)
;    to next chunk (or 0)
;
CH_INC_S	EQU	64*4-1
CHM_INC_S	EQU	64*4-1
IF_INC_S	EQU	$100-1
IX_INC_S	EQU	8-1
XLST_INC_S	EQU	32-1
HEAP_SPACE	EQU	$4C000
PC_SZE	EQU	1024*6+4
ALC_MAX	EQU	$8000
ALC_MIN	EQU	$2000

;
BUF_SIZE	EQU	60
CHLEN	EQU	512
LLEN	EQU	520
SEC	EQU	8
CI_SZE	EQU	$4000
LN1	EQU	12        single length of packed mantissa
LN2	EQU	24        double length of packed mantissa
N1	EQU	12        relative place in BUF for numbers
N2	EQU	N1+LN1                  "
N3	EQU	N2+LN1                  "
PAR_SZE	EQU	32        max parameter size for macros
;
	BRA.S	START
	DS.L	1
	DC.W	$4AFB
	DC.W	T_END-T_START
T_START	DC.B	"GWASS",VNUM," V",VERSION
T_END	DS.B	0
;
START	LEA	(A6,A5.L),A0        STACK
	LEA	(A6,A4.L),A6        -> DATA SPACE
	MOVE.L	A0,STACK(A6)
	MOVE.L	#-1,NO_ERRS(A6)     inhibit error printing 1st time
	CLR.L	LINE_NO(A6)         in case of FATAL ERROR
	MOVE.W	(A7)+,D1
	MOVEA.L	A7,A4               -> STRING?
	SUBQ.W	#1,D1
	BMI	NO_CHAN
	LSL.W	#2,D1
	MOVEA.L	(A7,D1.W),A0        CH_ID
	LEA	4(A7,D1.W),A4       -> STRING
	BRA.S	NOTE_CHAN
NO_CHAN	LEA	CON,A1
	MOVE.W	UT_CON,A2
	JSR	(A2)
NOTE_CHAN	MOVE.L	A0,ID_CON(A6)
	CLR.B	BATCH(A6)
	MOVEM.L	A7,-(A7)            to test if 68020+
	CMPA.L	(A7),A7             equal if OK
	ADDQ.L	#4,A7               restore stack
	BNE	QER32               ---->
	MOVEQ	#0,D0	set both DATAD & PROGD
	BSR	SET_DP
	MOVE.W	#$100,D1
	TST.B	DEF_CD
	BEQ	SDEF
	BSET	#0,D1
SDEF	MOVE.B	DEF_68,D0
	BFINS	D0,D1{28:3}
	TST.B	DEF_EA
	BEQ	SDEF_1
	BSET	#4,D1
SDEF_1	TST.B	DEF_EL
	BEQ	SDEF_2
	BSET	#5,D1
SDEF_2	TST.B	DEF_UX
	BEQ	SDEF_3
	BSET	#9,D1
SDEF_3	TST.B	DEF_PC
	BEQ	SDEF_4
	BSET	#10,D1
SDEF_4	TST.B	DEF_REL
	BEQ	SDEF_5
	BSET	#11,D1
SDEF_5	TST.B	DEF_COM
	BEQ	SDEF_6
	BSET	#12,D1
SDEF_6	MOVE.W	D1,DEFAULT(A6)   set defaults
	MOVEQ	#0,D5     mark 'default _SYM'
	MOVE.W	(A4)+,D6  string length
	BEQ	START8    not batch or alt _SYM file
	LEA	TEMP_BUF(A6),A3
	CMPI.W	#PC_TOT-CH_IN-20,D6
	BGT	QER18     ----> string too long (>1408 bytes)
	MOVE.W	D6,D0
	SUBQ.W	#1,D0
	LSR.W	#1,D0     round down to words
START4	MOVE.W	(A4)+,(A3)+
	DBF	D0,START4 put string to TEMP_BUF
	MOVE.B	#'/',TEMP_BUF(A6,D6.W)   mark end
	MOVE.B	#'*',TEMP_BUF+1(A6,D6.W) of string
	MOVEA.L	STACK(A6),A7  set stack and overwrite string
	LEA	TEMP_BUF(A6),A4     -> start
	CLR.B	PC_TOT(A6)          space to note ACTIONS
START12	MOVE.B	(A4)+,D0  1st character
	CMPI.B	#$29,D0
	BLS	QER19     ---->
	CMPI.B	#$7A,D0   'z'
	BHI	QER19     ---->
	CMPI.B	#"*",D0
	BEQ	START8    end
	CMPI.B	#'Z',D0
	BLS	START5
	SUBI.B	#32,D0    to upper case
START5	CMPI.B	#"A",D0
	BEQ	A_ACTION  list of _ASM files
	CMPI.B	#"D",D0
	BEQ	D_ACTION
	CMPI.B	#"Q",D0
	BNE	QER19     ----> FATAL
;
; Q_action - set EQU_SYM filename
;
	BSET	#0,PC_TOT(A6)       mark Q_ACTION
	BNE	QER29     ---->
	MOVEA.L	A4,A1
Q_ACTION1	MOVE.B	(A1)+,D0  next char
	CMPI.B	#'/',D0
	BNE	QER29     ----> FATAL
	BSR	STRG
	BMI	QER29     ----> FATAL
	LEA	O_BUF(A6),A0 space for filename
	MOVE.L	A0,D5     and keep address in D5
	MOVE.W	(A2),D1   string length
	CMPI.W	#126,D1   a longer length is likely an error
	BGT	QER20     ----> FATAL
	ADDQ.W	#1,D1
	LSR.W	#1,D1     round to higher word
Q_ACTION2	MOVE.W	(A2)+,(A0)+  put to O_BUF
	DBF	D1,Q_ACTION2
	MOVEA.L	A1,A4
	BRA	START12
;
A_ACTION	BSET	#2,PC_TOT(A6)       mark A_ACTION
	BNE	QER19     ---->
	ST	BATCH(A6) mark batch
	CLR.L	TOT_BERRS(A6)       clear total errors
	MOVEA.L	A4,A1
	MOVE.B	(A1)+,D0
	CMPI.B	#"/",D0
	BNE	QER19     ----> FATAL
	MOVE.L	D5,D2     keep D5
	MOVE.B	(A1)+,D0
	BSR	DEC       to get no. of files
	BNE	QER19     ----> FATAL
	EXG	D5,D2
	CMPI.L	#MAX_FLES,D2
	BGT	QER21     ----> FATAL
	TST.L	D2
	BEQ	QER22     ----> FATAL
	CMPI.B	#'/',D0
	BNE	QER23     ----> FATAL
	MOVE.W	D2,D7
	MOVEA.L	A1,A4
	MOVE.L	D2,D1
	ADD.L	D1,D1
	EXT.L	D6
	ADD.L	D6,D1     len + 2*n
	ADDQ.L	#4,D1     for safety
	MOVEQ	#-1,D2    this job
	MOVEQ	#MT_ALCHP,D0
	TRAP	#1        get space
	TST.L	D0
	BNE	QER4      ----> FATAL
	MOVE.L	A0,BF_ADDR(A6)      file list address
	MOVEA.L	A4,A1     restore A1
	BRA	A_ACTION1
A_ACTION4	BSR	STRG      get next file
	BMI	QER19     ----> FATAL
	CMPI.B	#'/',D0
	BNE	QER23     ----> FATAL
	TST.W	D2        count
	BEQ	A_ACTION1 no file!!
	ADDQ.W	#1,D2
	LSR.W	#1,D2               round to higher word
A_ACTION3	MOVE.W	(A2)+,(A0)+         filename to BF_ADDR
	DBF	D2,A_ACTION3
A_ACTION1	DBF	D7,A_ACTION4        count files
	CLR.W	(A0)                mark end of files
	MOVE.L	BF_ADDR(A6),B_FLS(A6) point to 1st file
	MOVEA.L	A1,A4
	BRA	START12
;
D_ACTION	BSET	#1,PC_TOT(A6)
	BNE	QER30     ---->
	MOVEA.L	A4,A1
	MOVE.B	(A1)+,D0
	CMPI.B	#'/',D0
	BNE	QER30     ---->
	MOVE.L	D5,D2
	MOVE.B	(A1)+,D0
	BSR	DEC
	BNE	QER30     ---->
	EXG	D5,D2
	CMPI.L	#MAX_D,D2
	BGT	QER30     ---->
	CMPI.B	#'/',D0
	BNE	QER31     ---->
	CLR.W	DEFAULT(A6)
	BSET	#0,D2
	BEQ.S	D_ACTION1
	BSET	#0,DEFAULT+1(A6)
D_ACTION1	BFINS	D2,DEFAULT(A6){5:3}
	BTST	#8,D2
	BEQ	D_ACTION2		O_FILE
	BSET	#3,DEFAULT(A6)	REL_FILE
D_ACTION2	LSR.W	#3,D2
	BFINS	D2,DEFAULT+1(A6){2:5}
	MOVEA.L	A1,A4
	BRA	START12
;
CON	DC.B	230,2     border
	DC.B	BLACK,GREEN         paper/ink
	DC.W	340,84,100,50
;
SRT	DC.L	UMT1-SRT  to allow 16-bit jumps ...
	DC.L	INK-SRT   ... to UMT1 & INK
;
START8	MOVEA.L	STACK(A6),A7  set stack and overwrite string
	MOVE.L	#HEAP_SPACE,D1
	MOVEQ	#-1,D2    this JOB
	MOVEQ	#MT_ALCHP,D0
	TRAP	#1
	TST.L	D0
	BNE	QER4      ----> FATAL ERROR!!
	MOVE.L	A0,BLLAB(A6)
	MOVE.W	#128,LBUF-2(A6)     shows "\" in a MACRO line
	LEA	ER_SPACE(A6),A0
	MOVE.L	A0,ER_LST(A6)
	LEA	CRT_SEC(A6),A0
	MOVE.L	A0,TER_LST(A6)
	CLR.W	COMP_MARK(A6)
	CLR.B	F_EA(A6)
	CLR.B	BF(A6)
	MOVE.L	#$10000,ITEM(A6)
	PEA	FILEDEV
	PEA	PROMPT(A6)
	BSR	QSTRCPY
	ADDQ.L	#8,A7
;
;  Loads EQU3_SYM
;    to BLLAB
;
; (A null filename is treated as a zero file)
;
	MOVEQ	#-1,D1    this JOB
	MOVEQ	#0,D3
	TST.L	D5
	BEQ.S	START3    default
	LEA	O_BUF(A6),A0        set input filename
	BRA.S	START10
START3	LEA	EQU_SYM,A0
START10	MOVE.L	BLLAB(A6),BLLAB1(A6) set zero EQU_SYM
	MOVE.L	#1,SL1(A6)
	MOVE.W	#2,SL1+4(A6)
	TST.W	(A0)
	BEQ	START13
	BSR	OPENFILE
	BNE	QER13     ----> FATAL ERROR!!
	MOVEQ	#64,D2
	MOVEQ	#-1,D3
	MOVEA.L	BLLAB(A6),A1
	MOVEA.L	A1,A2
	MOVEQ	#FS_HEADR,D0
	TRAP	#3
	TST.L	D0
	BNE	QER2      ----> FATAL ERROR!!
	MOVE.L	(A2),D4   file length
	BEQ	START9    no file
	CMPI.L	#MAX_EQU,D4
	BGE	QER25     ---->
	MOVEQ	#$3E,D2
	CMP.L	D2,D4
	BLT	QER25     ---->
	LEA	BUF(A6),A1
	MOVEQ	#IO_FSTRG,D0
	TRAP	#3
	TST.L	D0
	BNE	QER3      ----> FATAL ERROR!!
	MOVE.L	D2,D0
	MOVEQ	#11,D1    count
	LEA	$C+BUF(A6),A1
START11	ADD.L	(A1)+,D0
	DBF	D1,START11
	CMP.L	D0,D4
	BNE	QER25     ---->
	MOVEQ	#2,D0
EQU_IN1	CMP.W	BUF(A6,D0.W*2),D0
	BNE	QER3      ---->
	CMPI.W	#8,6+BUF(A6,D0.W*2)
	BGT	QER3      ---->	must be start or none
	DBF	D0,EQU_IN1
	MOVEA.L	BLLAB(A6),A1        start of input
	LEA	$C+BUF(A6),A3
	MOVE.L	#$30000,$40+BUF(A6) set up 'odd' name
	MOVEQ	#3,D4
EQU_IN2	SWAP	D4
	MOVE.W	#2,D4
EQU_IN3	MOVE.L	(A3)+,D2
	BEQ	EQU_IN4   no chunks
	PEA	EQU_IN4
	MOVE.W	D4,D0
	LSL.W	#2,D0
	NEG.W	D0
	SWAP	D4
	ADD.W	EQ_TAB(D4.W*2),D0
	SWAP	D4
	MOVE.L	A1,(A6,D0.W)        set 1st address of strand
	BTST	#16,D4
	BEQ	EQU_SL
	BRA	EQU_SN
;
EQ_TAB	DC.W	LINN+8
	DC.W	LAB_LST+8
	DC.W	SINN+8
	DC.W	SEC_LST+8
;
EQU_IN4	DBF	D4,EQU_IN3
	SWAP	D4
	DBF	D4,EQU_IN2
	MOVE.W	$3C+BUF(A6),D0      next section no
	MOVE.W	D0,SEC_NO(A6)
	SUBQ.W	#1,D0
	MOVE.W	D0,CRT_SEC(A6)
	MOVEA.L	A1,A2     set BLLAB1 for HEAP start
START9	MOVE.L	A2,BLLAB1(A6)
	MOVEQ	#IO_CLOSE,D0
	TRAP	#2
START13	CLR.W	PROGD(A6)	we don't want this any more
	LEA	DEND(A6),A0         end of data space
	ADDA.W	#256,A0
	MOVE.L	A0,G_LIMIT(A6)      lowest value of STACK for GLABx
;
; Clear   MAC_LST, SEC_LST, MINN, SINN and LINN (4th)
; Clear   LAB_LST & LINN from SLi

;
; If not BATCH: set paper black and ink green
;
	TST.B	BATCH(A6)           BATCH? . . .
	BNE	GWAG                . . . yes
	MOVEQ	#-1,D3              timeout
	MOVEA.L	ID_CON(A6),A0
	MOVEQ	#BLACK,D1
	MOVEQ	#SD_SETPA,D0
	TRAP	#3
	MOVEQ	#SD_SETST,D0
	TRAP	#3
	MOVEQ	#GREEN,D1
	BSR	INK
GWAG	MOVEQ	#17,D0
	LEA	EQB(A6),A0
GWAG0	CLR.L	(A0)+
	DBF	D0,GWAG0
	MOVEQ	#63,D0
	LEA	CO_SE(A6),A0
GWAG11	CLR.L	(A0)+	Clear CO_SE to 'SECTION'
	DBF	D0,GWAG11
	MOVE.L	#EQU_INC_S,EQU_INC(A6)
	MOVE.L	#CH_INC_S,CH_INC(A6)
	MOVE.L	#CHM_INC_S,CHM_INC(A6)
	MOVE.L	#IF_INC_S,IF_INC(A6)
	MOVE.L	#IX_INC_S,IX_INC(A6)
	MOVE.L	#XLST_INC_S,XLST_INC(A6)
	CLR.L	PC_CS1(A6)
	CLR.L	X_ALLOC1(A6)
	CLR.L	PC_CS(A6)
	CLR.B	ORG_H(A6)	set 'no ORG'
	MOVE.L	#-1,PC_TH(A6)
	MOVEQ	#2,D4     strand count
S_LST	CLR.L	MAC_LST(A6,D4.W*4)
	CLR.L	SEC_LST(A6,D4.W*4)
	CLR.L	MINN(A6,D4.W*4)
	CLR.L	SINN(A6,D4.W*4)
	MOVE.W	SL1(A6,D4.W*2),D3   1st label no after EQU
	BFEXTU	D3{16:14},D1        number inside strand
	BEQ	S_LST1              no EQU in this strand
	BSR	GNL       A2 -> LAB name, A0 -> start of chunk
	BMI	S_LST2    nothing to do
	MOVE.L	A2,(A0)   mark SLi as last name
	CLR.L	4(A0)     see that there are no more chunks
	MOVE.W	D3,D1
	BSR	CHK_L     A0 -> item in LINN
	BEQ.S	S_LST2    no LINN
	BFEXTU	D1{24:6},D0         offset/8 for that item
	NEG.W	D0
	CLR.L	-8(A0,D0.W*8) make chunk the last one
	MOVE.W	#-2,(A0)  clear that item
S_LST2	DBF	D4,S_LST
	CLR.L	LINN+12(A6)         dummy label area
	CLR.W	SEC_NO(A6)          clear sections
	MOVEA.L	BLLAB1(A6),A0
	MOVE.L	BLLAB(A6),D1
	SUB.L	A0,D1
	ADDI.L	#HEAP_SPACE-16,D1
	MOVE.L	D1,D2
	LSR.L	#2,D2
	BRA	HEAP1
;
S_LST1	CLR.L	LAB_LST(A6,D4.W*4)
	CLR.L	LINN(A6,D4.W*4)
	BRA	S_LST2
;
HEAP3	SWAP	D2
HEAP2	CLR.L	(A0)+
HEAP1	DBF	D2,HEAP2
	SWAP	D2
	DBF	D2,HEAP3
	MOVEA.L	BLLAB1(A6),A0
	LEA	HEAPAD(A6),A1
	CLR.L	(A1)
	MOVEA.W	MM_LNKFR,A2
	JSR	(A2)      set up the user heap
;
; Now set EQU labels to '5'
;
	MOVEQ	#2,D0
SLAB1	MOVE.W	D0,D1
	BSR	LNPTR     A0 -> LINN
	BEQ	SLAB2     no strand
SLAB4	LEA	LLEN-8(A0),A2       -> end of strand
SLAB3	CMPI.W	#-2,(A0)  end of labels? . .
	BEQ	SLAB2     . . yes
	MOVE.W	#5,TYPE(A0)  set type 5
	LEA	8(A0),A0  next item
	CMPA.L	A2,A0     end of chunk? ....
	BLT.S	SLAB3     .... no
	MOVE.L	-LLEN(A2),D1        -> next chunk
	BEQ	SLAB2     end of chunks
	LEA	8(D1.L),A0          -> 1st label
	BRA	SLAB4
SLAB2	DBF	D0,SLAB1  count strands
	CLR.W	CHM_NO(A6)
	CLR.L	BIN_OUT(A6)
	CLR.B	BIN_SWTCH(A6)
	CLR.B	ER_EA(A6)
	CLR.W	MAC_NO(A6)
	CLR.W	MAC_CT(A6)
	MOVE.W	#1,XREF_NO(A6)      set 1st no to 1
	MOVE.W	DEF_PCK,PCK(A6)
	MOVE.W	DEF_PWID,PWID(A6)
	MOVE.L	DEF_DATA,DATA(A6)
GWAG1_0	MOVEQ	#-1,D4    mark normal
;
GWAG1	MOVEA.L	ID_CON(A6),A0
	MOVEQ	#-1,D3
	LEA	HEAD0_B,A1          batch Heading
	TST.B	BATCH(A6) batch mode? . . .
	BNE	GWAG1_1   . .  . . . yes
	MOVEQ	#SD_CLEAR,D0
	TRAP	#3        clears window
	MOVE.B	CON,D1    color -> D1
	MOVE.B	CON+1,D2
	EXT.W	D2        width -> D2
	MOVEQ	#SD_BORDR,D0
	TRAP	#3
	LEA	HEAD0,A1
GWAG1_1	TST.B	BF(A6)
	BNE	GWAG1_3
	LEA	SRT,A3
	ADDA.L	(A3),A3   -> UMT1
	JSR	(A3)      allows a large jump
GWAG1_3	TST.B	BATCH(A6) BATCH? . . .
	BEQ	GWAG1_2   . . . no
	ST	BF(A6)
	TST.W	D4
	BMI	GWAG5     normal
	BRA	QERX_3    fatal error
GWAG1_2	TST.W	D4
	BMI.S	GWAG4     normal
	MOVE.B	D4,D1
	LEA	SRT,A3
	ADDA.L	4(A3),A3  -> INK
	JSR	(A3)
	LSR.W	#8,D4
GWAG4	LEA	HEAD0A,A1
	LEA	SRT,A3
	ADDA.L	(A3),A3   -> UMT1
	JSR	(A3)      allows a large jump
	TST.W	D4
	BMI.S	GWAG3     normal
	MOVE.B	D4,D1
	LEA	SRT,A3
	ADDA.L	4(A3),A3  -> INK
	JSR	(A3)
	LEA	HEAD0B,A1
	LEA	SRT,A3
	ADDA.L	(A3),A3   -> UMT1
	JSR	(A3)      allows a large jump
	MOVE.B	#GREEN,D1
	LEA	SRT,A3
	ADDA.L	4(A3),A3  -> INK
	JSR	(A3)
	BRA	QERX_3    ---->
GWAG3	LEA	HEAD0B,A1
	BSR	UMT1
	BRA	GWAG_NORM
;
; BATCH action
;
GWAG5	MOVE.L	NO_ERRS(A6),D0
	BMI.S	GWAG8
	ADD.L	D0,TOT_BERRS(A6)    cleared in A_ACTION
GWAG8	MOVEA.L	B_FLS(A6),A0        next _ASM file
	MOVEA.L	A0,A5     keep address in A5
	MOVE.W	(A5)+,D0  length
	MOVE.W	D0,D1     keep length
	BNE	GWAG9     not ended
	TST.L	NO_ERRS(A6)
	BMI	GWAG10    ERRORs and WARNINGs done already
	BSR	GWAG_NOR1 print number of ERRORs and WARNINGs
GWAG10	MOVE.L	TOT_BERRS(A6),D3
	BEQ	QUIT2     exit with no errors
	MOVEQ	#-1,D3    set 'not complete' to indicate ERRORs
	BRA	QUIT2     ended
GWAG9	ADDQ.W	#1,D0
	LSR.W	#1,D0     round to higher word
	LEA	(A5,D0.W*2),A1      -> next file
	MOVE.L	A1,B_FLS(A6)
	CMPI.W	#40,D1
	BGT	BEEP      ignore - too long
	LEA	PROMPT(A6),A1
	MOVE.W	D1,(A1)+
	BRA.S	GWAG6
GWAG7	MOVE.B	(A5)+,(A1)+   set filename in PROMPT
GWAG6	DBF	D1,GWAG7
	TST.L	NO_ERRS(A6)
	BMI	TEST_NAME
	MOVE.L	A0,-(A7)
	BSR	GWAG_NOR1
	MOVEA.L	(A7)+,A0
	BRA	TEST_NAME
;
GWAG_NOR1	BSR	PRERS     set up BUF with no of errors & warnings . .
	MOVE.L	#-1,NO_ERRS(A6)     stop it
	BRA	UMT       . . and print it
;
GWAG_NORM	BSR	CURON     put on cursor
	TST.L	NO_ERRS(A6)
	BMI	GWAG2     processing not done - ignore
	BSR	GWAG_NOR1
;
;         Menu
;
GWAG2	MOVEQ	#IO_FBYTE,D0
	TRAP	#3
	CMPI.B	#244,D1
	BEQ	GWAG1_0	F4 - redraw
	ADDQ.B	#1,D1
	CMPI.B	#'2',D1
	BEQ.S	REPRINT
	CMPI.B	#'3',D1
	BNE.S	GWAG2     get 1,2, or F4
REPRINT	MOVE.B	D1,D2
	SUB.B	#48,D2
	MOVE.B	D2,D7     keep 1,2 in D7
	MOVEQ	#WHITE,D1
	BSR	INK
	MOVEQ	#0,D1
	BSR	AT
	CMPI.B	#2,D2
	BEQ.S	REP1      process
	LEA	HEAD0B,A1
	BRA.S	REP2      quit
REP1	MOVEQ	#1,D0	ask for DATAD only
	BSR	SET_DP
	LEA	HEAD0A,A1
REP2	BSR	UMT1
	MOVEQ	#GREEN,D1
	BSR	INK
	BSR	CUROF
	CMPI.B	#2,D7
	BNE	QUIT1     EXIT for good!
REP3	MOVEQ	#0,D1    re-entry after BEEP
	MOVEQ	#5,D2
	BSR	AT
	LEA	HEAD1,A1
	BSR	UMT1
	MOVEQ	#SD_NL,D0
	TRAP	#3        new line
	LEA	BUF(A6),A1    to get X-POS etc
	MOVEQ	#SD_CHENQ,D0
	TRAP	#3
	MOVE.W	BUF+4(A6),D1  X-POS
	SWAP	D1
	MOVE.W	PROMPT(A6),D1
	MOVE.W	#40,D2    buffer length
	LEA	PROMPT+2(A6),A1
	ADDA.W	D1,A1
	MOVEQ	#IO_EDLIN,D0
	TRAP	#3
	LEA	PROMPT(A6),A0
	MOVE.L	A1,D0
	LEA	PROMPT+2(A6),A1
	SUB.L	A1,D0
	SUBQ.W	#1,D0
	MOVE.W	D0,(A0)   set length of name
	BEQ	GWAG1_0	No file - try again
;
; batch entry point
;
TEST_NAME	MOVEQ	#0,D3     OPEN_IN
	BSR	OPENFILE
	BNE	BEEP      can't open - try again
	MOVEQ	#64,D2    header length
	MOVEQ	#-1,D3
	LEA	O_BUF(A6),A1  space for header
	MOVEQ	#FS_HEADR,D0
	TRAP	#3
	TST.L	D0
	BNE	BEEP1     can't read header!!
	TST.B	-59(A1)   check type
	BNE	BEEP1     not type 0
	MOVE.L	A0,CH_IN(A6)
	PEA	CH_LST(A6)
	PEA	4         length needed
	PEA	0         mark 'no relocation'
	BSR	GSP
	LEA	12(A7),A7
	MOVE.L	A0,([CH_LST,A6])
	CLR.W	CH_NO(A6)
	LEA	PROMPT-2(A6),A1
	ADDA.W	2(A1),A1  set A1 to 4 bytes from the end of filename
	LEA	BUF(A6),A0
	MOVE.W	#4,(A0)+  set length
	MOVEQ	#3,D0     count
GW6	MOVE.B	(A1)+,(A0)+
	DBF	D0,GW6
	LEA	BUF(A6),A1
	LEA	TRAIL1,A0 "_ASM"
	MOVEQ	#1,D0     ignore case
	MOVEA.L	A6,A5     keep A6
	SUBA.L	A6,A6
	MOVE.W	UT_CSTR,A2
	JSR	(A2)
	TST.L	D0
	BEQ.S	GW1
	MOVEQ	#4,D0     no _ASM - add 4 to length
GW1	MOVEA.L	A5,A6     restore A6
	LEA	BUF+2(A6),A0
	LEA	PROMPT(A6),A1
	ADD.W	(A1)+,D0  D0=length of name ex _ASM - 4
	MOVE.W	D0,-2(A0) insert length in BUF
	SUBQ.W	#4,D0
	BRA.S	GW2
;
SAVE_NME	BTST	#1,D4
	BEQ.S	SAVE_NM4  _TMP
	LEA	BIN_NME(A6),A5
	BRA.S	SAVE_NM3
SAVE_NM4	LEA	TMP_NME(A6),A5
SAVE_NM3	MOVE.W	(A0)+,D0  length of name
	MOVE.W	D0,(A5)+
	CMPI.W	#38,D0
	BGT	SAVE_NM5
	BRA.S	SAVE_NM1
SAVE_NM2	MOVE.B	(A0)+,(A5)+
SAVE_NM1	DBF	D0,SAVE_NM2
SAVE_NM5	RTS
;
GW3	MOVE.B	(A1)+,(A0)+         filename to BUF
GW2	DBF	D0,GW3
	MOVEQ	#3,D4     for 4 files
	LEA	CH_OUT(A6),A3
	LEA	TRAIL2,A2
GW4	MOVEQ	#3,D0
	MOVEA.L	A2,A1
	ADDQ.L	#4,A2
GW5	MOVE.B	(A1)+,(A0)+
	DBF	D0,GW5
	LEA	BUF(A6),A0    reset A0
	BTST	#0,D4     BIN or TMP file?
	BEQ	GW7
	BSR	SAVE_NME  yes
	LEA	BUF(A6),A0
GW7	MOVEQ	#3,D3     OPEN_OVER
	BSR	OPENFILE
	BNE	BEEP
	MOVE.L	A0,(A3)+
	LEA	BUF-2(A6),A0
	ADDA.W	2(A0),A0
	DBF	D4,GW4
	CLR.L	(A3)	set ID of _o 'zero'
	CLR.L	BINS(A6)
	CLR.L	BIN_F(A6)
	CLR.L	BIN_L(A6)
	LEA	([ER_LST,A6],4),A0
	MOVE.L	A0,-4(A0)
	CLR.L	LINE_NO(A6)
	BSR	ST_LNO    sets PC_TH & PC_PR
	CLR.L	MARK(A6)
	MOVE.L	#-1,IF_LNO(A6)
	CLR.W	ACT_L(A6)
	CLR.W	IF_L(A6)
	CLR.B	TEMP_ON(A6)
	ST	IF_SW(A6)
	SUBA.L	A5,A5     set PC to 0
	TST.B	BATCH(A6) if BATCH . . .
	BNE	GWSET10   . . print filename
	LEA	HEAD2,A1  print "PASS 1"
	BRA	GWSET9
GWSET10	LEA	PROMPT(A6),A1
GWSET9	BSR	UMT
	LEA	O_BUF+4(A6),A0   Set O_BUF for
	MOVE.L	A0,-4(A0)    output to _BIN
	LEA	SEC_PC(A6),A0
	MOVE.W	#255,D0
GWSET6	CLR.L	(A0)+
	DBF	D0,GWSET6
	CLR.W	REL_SWTCH(A6)       clears DIP too
	MOVE.B	DEFAULT+1(A6),DIP(A6)
	MOVE.W	#-1,CRT_SEC(A6)     set for normal
	CLR.L	PC_TOT(A6)
	CLR.L	PC_INST(A6)
	CLR.L	RS(A6)
	CLR.L	P_MAC(A6)	set zero 'P' file chain
	CLR.W	FLTYP(A6)
	MOVE.W	#-1,E_COM(A6)	set no 'COMMON'
	BSR	SET_MNE   sets Module name = Prompt
;
; PC_LST item is 'PC' (lwd) followed by 'section' (wd)
;  This is held in a set of chained chunks each PC_SZE long.
;  The 1st long word points to the next link or is zero.
;  PC_TH and PC_PR point to the current and previous 6 bytes .
;
GLIN	CLR.B	F_EA(A6)      clear EA jump marker
	CLR.B	ER_EA(A6)     clear EA error jumper
	MOVE.L	A5,D3
	ADD.L	D3,([PC_TH,A6]) set PC and SECTION to PC_LST
	MOVE.W	CRT_SEC(A6),([PC_TH,A6],4)
	LEA	OBUF+4(A6),A0   Reset the pointers to
	MOVE.L	A0,-4(A0)       OBUF (for [EXT])
GLIN1
	LEA	LBUF(A6),A1
	MOVE.L	CH_IN(A6),D7  D7 is minus for MACRO
	MOVE.L	D7,D2
	BCLR	#31,D2
	BEQ.S	GLIN2
	LEA	MAC_BUF(A6),A1   line  -> MAC_BUF for MACRO
GLIN2	MOVEA.L	D2,A0
	MOVE.W	#256,D2
	MOVEQ	#-1,D3
	MOVEQ	#IO_FLINE,D0
	TRAP	#3
	TST.L	D0
	BEQ.S	DO_LINE
	CMPI.B	#-10,D0
	BNE	QER8      ---->
	TST.W	D1        any bytes fetched?
	BEQ	IN_END    no
	MOVE.B	#10,(A1)  put LF in buffer
	ADDQ.W	#1,D1     and adjust count
;
DO_LINE	TST.L	D7        MACRO?
	BMI	MAC_LN    yes
DO_LINE1	LEA	LBUF(A6),A1
DO_LINE2	MOVEA.L	CH_TMP(A6),A0
	MOVE.W	D1,D2     no of bytes fetched
	MOVEQ	#IO_SSTRG,D0
	TRAP	#3
	TST.L	D0
	BNE	QER9      ---->
	SUBA.W	D1,A1     reset pointer to instruction line
	MOVE.B	(A1)+,D0
	CMPI.B	#32,D0
	BEQ	DO_INSTR
	CMPI.B	#9,D0     TAB
	BEQ	DO_INSTR
	BSR	CH_LET
	SUBQ.L	#1,A1     (cond codes not affected)
	BEQ	DO_LAB
	TST.L	IF_LNO(A6)
	BMI	INST_ED1	no IFs or between ENDIF and the next IF
	ADDQ.L	#1,IF_LNO(A6)  ignore comment lines for AND/OR_IF
INST_ED1	ADDQ.L	#1,LINE_NO(A6)
	BSR	ST_LNO    reset PC_TH & PC_PR
	LEA	OBUF(A6),A4
	MOVEA.L	(A4)+,A0
	BRA.S	I_END1
I_END2	MOVE.W	(A4)+,D5
	BSR	PUT_W
I_END1	CMPA.L	A0,A4
	BLT.S	I_END2
	BRA	GLIN
INST_END	BSR	PUT_W
	BRA.S	INST_ED1
;
; Replaces PC in A5 after an error
;
INST_ED2	LEA	O_BUF(A6),A0
	MOVE.L	(A0)+,D1
	SUB.L	A0,D1     amount in O_BUF
	ADD.L	BIN_OUT(A6),D1      file position  now
	ADD.L	PC_INST(A6),D1      A5 value at start of inst.
	SUB.L	PC_TOT(A6),D1       file pos.     "
	MOVE.L	D1,A5     reset PC
	LEA	OBUF+4(A6),A0
	MOVE.L	A0,OBUF(A6)         clear OBUF
	MOVE.L	EA_INSMK1(A6),BINS(A6)
	MOVE.L	EA_INSMK(A6),([BINS,A6]) reset INS position
	TST.L	([BINS,A6],-8)
	BEQ	INST_ED1  no further chunk
	MOVEA.L	([BINS,A6],-8),A0
	LEA	12(A0),A0
	MOVE.L	A0,-4(A0) clear the further chunk
	BRA.S	INST_ED1
;
; MACRO lines are adjusted
;  for parameters (\x) local LABELS (\@)
;  and <values> (| ... ~) from MAC_BUF <-> LBUF
;
MAC_LN	LEA	MAC_BUF(A6),A1
	CMPI.B	#128,(A1) '\' or '|' in line?...
	BNE	DO_LINE2  ... no
	CLR.L	-(A7)     space for end of buffer address
	MOVEA.L	A1,A4     set A4 -> MAC_BUF
	LEA	LBUF(A6),A3
	MOVE.W	D1,D6     keep D1 in D6
	SUBQ.W	#1,D1
	ADDQ.L	#1,A1     go past '128'
	MOVEQ	#-1,D5	mark 1st time
	CLR.W	D5	mark not <value>
	BRA	MAC_LP1
MAC_LP	EXG	A3,A4     switch buffers
	MOVEA.L	A4,A1     set input
MAC_LP1	LEA	256(A3),A2          -> end of buffer
	MOVEM.L	A2,(A7)
	MOVEA.L	A3,A2     set output
	BNE	MAC_VAL   go to <value> if D5.W <>0
	SUBQ.W	#1,D1     set count-1 for DBF
	MOVEQ	#-1,D4    mark no '|' yet
MAC_LN3	MOVE.B	(A1)+,D0
	TST.L	D5	1st time? . .
	BPL	MAC_LN8	. . no
	CMPI.B	#'\',D0	only replace \x by . .
	BEQ.S	MAC_LN4	. . values in 1st pass
MAC_LN8	CMPI.B	#"|",D0
	BEQ	MAC_VI    mark start of <value>
	CMPI.B	#"~",D0
	BEQ	MAC_VO    mark end of <value>
MAC_LN5	CMPA.L	(A7),A2   too much? . .
	BGE	MAC_ER33  . . yes
	MOVE.B	D0,(A2)+
MAC_OX	DBF	D1,MAC_LN3
MAC_LN6	MOVE.L	A2,D1     end of new buffer
	SUB.L	A3,D1     new length
	TST.W	D5        any <value>? ...
	BNE	MAC_LP    ... yes - do it
	MOVEA.L	A3,A1     set to start of buffer
	MOVEQ	#-1,D3    reset D3 for timeout
;
; Replace zero bytes by '\'
;
	MOVE.W	D1,D2     count
	BRA	MAC_LN2
MAC_LN7	TST.B	(A3)+     for \? . .
	BNE	MAC_LN2   . . no
	MOVE.B	#'\',-1(A3)
MAC_LN2	DBF	D2,MAC_LN7
	ADDQ.L	#4,A7     adjust stack
	BRA	DO_LINE2
MAC_LN4	MOVE.B	(A1)+,D0
	SUBQ.W	#1,D1     adjust count of chars in line
	CMPI.B	#'@',D0
	BEQ.S	MAC_AX
	MOVE.B	D0,D3
	BSR	MAC_PAR
	TST.B	D0
	BEQ	MAC_NUM
	BPL	MAC_FND
	MOVE.B	D3,D0
	CMPI.B	#'\',D0   2nd '\'? . .
	BNE	MAC_ER33 ---->
	CLR.B	D0        set byte to zero
	BRA	MAC_LN5   . . yes - ignore the 1st
;
MAC_FND	BSR	MAC_GP	D2 = length of parameter
	BRA	MAC_FND3
MAC_FND4	MOVE.B	-(A0),(A2)+	parameter -> line
MAC_FND3	DBF	D2,MAC_FND4
;	MOVE.W	(A7)+,D2
	BRA	MAC_OX
;
; On entry D0.B = parameter number (1 to 35)
; On exit  D2.W = size of parameter A0 -> parameter
;
MAC_GP	LEA	([8,A7],-6),A0
	BRA	MAC_GP4
MAC_GP5	LEA	([3*4+8,A7],-6),A0
MAC_GP4	MOVEQ	#0,D2	in case answer is zero
	EXT.W	D0
	BEQ	MAC_GP3	zero -> null parameter
	CMP.W	4(A0),D0
	BHI	MAC_GP3	parameters not entered -> null
	SUBQ.W	#1,D0
	BRA	MAC_GP1
MAC_GP2	MOVE.W	-(A0),D2  count
	SUBA.W	D2,A0     go to next parameter
MAC_GP1	DBF	D0,MAC_GP2
	MOVE.W	-(A0),D2  count
MAC_GP3	RTS
;
MAC_AX	MOVE.B	#'^',(A2)+
	LEA	BUF+10(A6),A0
	MOVE.L	D5,-(A7)
	MOVE.L	A0,D5
	MOVE.W	CHM_NO(A6),D0    current MAC..
	MOVE.W	([CHM_LST,A6],D0.W*8,-6),D0   .._CT
	EXT.L	D0
	MOVE.W	D1,D6
	BSR	LTOD
	MOVE.W	D6,D1
MAC_AX1	MOVE.B	(A0)+,(A2)+
	CMPA.L	D5,A0
	BLT.S	MAC_AX1
	MOVE.L	(A7)+,D5
	BRA	MAC_OX
;
MAC_VAL	MOVE.B	#32,(A1,D5.W)       set marker @ end of <value>
	BRA.S	MAC_VAL1
MAC_VAL2	MOVE.B	(A1)+,(A2)+         copy bytes up
MAC_VAL1	DBF	D4,MAC_VAL2         to <value>
	ADDQ.L	#1,A1               jump over "|"
	MOVE.L	D1,D6     keep count
	CMPI.B	#'#',(A1)
	BEQ	MAC_FN	#functions
	BSR	GNUM
	CMPI.B	#1,D1
	BEQ	MAC_VALN  number
	CMPI.B	#-2,D1
	BNE	MAC_ER33A ----> not string or number
	BSR	MAC_STR   set string to A2
MAC_VAL5	SUB.W	D5,D6     get number of ...
	SUBQ.W	#1,D6     ... remaining bytes
	LEA	1(A4,D5.W),A1       point to after <value>
	BRA	MAC_VAL4
MAC_VAL3	MOVE.B	(A1)+,(A2)+
MAC_VAL4	DBF	D6,MAC_VAL3
	MOVE.L	A2,D1
	SUB.L	A3,D1     new count
	MOVEQ	#0,D5     set for 'normal' and mark not 1st time
	BRA	MAC_LP
;
MAC_FN	MOVEM.L	A1-3,-(A7)
	ADDQ.L	#1,A1	go past #
	BSR	STRG	get function
	BMI	MAC_ER74B	---->
	LEA	MA_LST,A0
	EXG	A2,A1
	MOVEQ	#MA_LEN,D1
	BSR	FIND
	EXG	A2,A1
	BMI	MAC_ER76B	---->
	CMPI.B	#'(',D0
	BNE	MAC_ER42B	----> ( expected
	LEA	MA_RLST,A0
	ADDA.W	(A0,D1.W*2),A0
	JMP	(A0)
;
MA_LST	DC.W	3
	DC.B	'LEN'
	DC.W	5
	DC.B	'INSTR'
	DC.W	4
	DC.B	'LEFT'
	DC.W	5
	DC.B	'RIGHT'
	DC.W	3
	DC.B	'DEF'
	DC.W	3
	DC.B	'ABS'
	DC.W	5
	DC.B	'UCASE'
	DC.W	4
	DC.B	'PLEN'
	DC.W	4
	DC.B	'PARM'
;
MA_LEN	EQU	9
MAB_LEN	EQU	11	number of ABS possibilities
MAB11	EQU	MAB7
MAB10	EQU	MAC_ER1B
MAB9	EQU	MACP5_1
MAB8	EQU	MACP5_2
MAB6	EQU	MAB7
MACP8	EQU	MACP9
;
	DS.W	0
	G_LST	MA_RLST,MACP,1,MA_LEN
	G_LST	MABS_L,MAB,1,MAB_LEN
;
; 1-> LEN 2-> INSTR 3 -> LEFT 4 -> RIGHT 5 -> DEF 6 -> ABS
; 7 -> UCASE 8 -> PARM
;
; UCASE
MACP7	BSR	GNUM
	ADDQ.L	#2,D1
	BNE	MAC_ER74B	---->
	CMPI.B	#')',D0
	BNE	MAC_ER43B	---->
	LEA	BUF(A6),A0	A0 ->string
	MOVE.W	(A0)+,D0		length
	BRA	MACP7_1
MACP7_2	MOVE.B	(A0)+,D1
	CMPI.B	#'a',D1
	BLT	MACP7_1		upper case already
	CMPI.B	#'z',D1
	BGT	MACP7_1		not a letter
	BCLR	#5,-1(A0)		set byte to upper case
MACP7_1	DBF	D0,MACP7_2
	LEA	BUF(A6),A0	A0 -> upper case string
	BRA	MACP3_4
;
; LEN
MACP1	BSR	GNUM
	ADDQ.W	#2,D1
	BNE	MAC_ER74B	---->
;	CMPI.B	#')',D0
;	BNE	MAC_ER43B	----> ) expected
	MOVE.W	BUF(A6),D2	set length
	BRA	MACP2_3
;
; INSTR (target,match)
MACP2	MOVEQ	#0,D3	mark INSTR
MACP2_7	BSR	GNUM
	ADDQ.L	#2,D1
	BNE	MAC_ER74B	---->
	CMPI.B	#',',D0
	BNE	MAC_ER19B	----> comma expected
	LEA	BUF(A6),A0     **********
	LEA	EX_BUF(A6),A2  *  Move  *
	MOVE.W	(A0)+,D0	     * target *
	MOVE.W	D0,(A2)+	     * string *
	BRA	MACP2_1	     *   to   *
MACP2_2	MOVE.B	(A0)+,(A2)+    * EX_BUF *
MACP2_1	DBF	D0,MACP2_2     **********
	BSR	GNUM
	CMPI.W	#1,D3
	BPL	MACP3_1
	ADDQ.L	#2,D1
	BNE	MAC_ER74B	---->
	CMPI.B	#')',D0
	BNE	MAC_ER43B	---->
	LEA	BUF(A6),A2	match string (m)
	LEA	EX_BUF(A6),A0	target string (t)
	MOVE.W	(A2)+,D2		lm
	BEQ	MACP2_3
	NEG.W	D2		-lm
	ADD.W	(A0)+,D2		lt-lm
	BPL	MACP2_4
	MOVEQ	#0,D2		no match possible
	BRA	MACP2_3
MACP2_4	MOVE.W	-2(A2),D1		lm
	MOVEA.L	A2,A3
	MOVEA.L	A0,A1
	SUBQ.W	#1,D1		lm-1
MACP2_5	CMPM.B	(A3)+,(A1)+
	DBNE	D1,MACP2_5
	BEQ	MACP2_6	found
	ADDQ.L	#1,A0	try from the next byte
	DBF	D2,MACP2_4	count 1+lt-lm times
	MOVEQ	#0,D2	mark not found
	BRA	MACP2_3
;
MACP2_6	NEG.W	D2		-ct
	SUB.W	-2(A2),D2		-ct-lm
	ADD.W	EX_BUF(A6),D2       lt-lm-ct
	ADDQ.W	#1,D2		lt-lm-ct+1
MACP2_3	MOVEM.L	(A7)+,A1-3
;
MAC_VALN	MOVE.L	D2,D0
	BSR	LTODZ     set signed ASCII
	BRA	MAC_VAL5
;
; LEFT
MACP3	MOVEQ	#1,D3	mark LEFT
	BRA	MACP2_7
;
MACP3_1	SUBQ.L	#1,D1
	BNE	MAC_ER75B	---->
	CMPI.B	#')',D0
	BNE	MAC_ER43B	---->
	TST.W	D2
	BPL	MACP3_2	set neg D2 to 0
	MOVEQ	#0,D2
MACP3_2	CMPI.B	#2,D3	1=left 2=right
	BEQ	MACP4_1
	CMP.W	EX_BUF(A6),D2
	BGE	MACP3_3
	MOVE.W	D2,EX_BUF(A6)
MACP3_3	LEA	EX_BUF(A6),A0
MACP3_4	MOVEM.L	(A7)+,A1-3
MACP3_5	PEA	MAC_VAL5
	BRA	MAC_STR3
;
; RIGHT
MACP4	MOVEQ	#2,D3	mark RIGHT
	BRA	MACP2_7
;
MACP4_1	MOVE.W	EX_BUF(A6),D0
	CMP.W	D0,D2	
	BLE	MACP4_2
	MOVE.W	D0,D2     limit o/put string to total length
MACP4_2	SUB.W	D2,D0     starting place
	LEA	EX_BUF(A6,D0.W),A0
	MOVE.W	D2,(A0)
	BRA	MACP3_4
;
MAC_T	DC.W	4
	DC.B	'TRUE'
MAC_F	DC.W	5
	DC.B	'FALSE'
;
; DEF
MACP5	BSR	GNUM
	ADDQ.W	#1,D1
	BEQ	MAC_ER1B	---->
	CMPI.W	#1,D1
	BEQ	MACP5_1	F
	CMPI.W	#5,D1
	BEQ	MACP5_1	F
MACP5_2	MOVEQ	#1,D2	True
	BRA	MACP2_3
MACP5_1	MOVEQ	#0,D2  	False
	BRA	MACP2_3
;
; ABS
;                            GNUM D1.L
; returns -1 = undefined	0 or 4
;	 0 = PC		2
;	 1 = numeric	1
;	 2 = string	-2
;	 3 = FP		-3
;	 4 = Quad word	-4
;	 5 = register list	-5
;	 6 = register	-6
;
MACP6	BSR	GNUM
	ADDQ.W	#6,D1
	BMI	MAC_ER1B	---->
	CMPI.W	#10,D1
	BGT	MAC_ER1B	---->
	LEA	MABS_L,A2
	ADDA.W	(A2,D1.W*2),A2
	JMP	(A2)
;
MAB1	MOVEQ	#6,D2	Register
	BRA	MACP2_3
MAB2	MOVEQ	#5,D2	Register list
	BRA	MACP2_3
MAB3	MOVEQ	#4,D2	Quad word
	BRA	MACP2_3
MAB4	MOVEQ	#3,D2	FP
	BRA	MACP2_3
MAB5	MOVEQ	#2,D2	String
	BRA	MACP2_3
MAB7	MOVEQ	#-1,D2	Undetermined or EQU list
	BRA	MACP2_3	or error in GNUM
;
; PLEN/PARM
;
MACP9	MOVE.W	D1,D3	7=PLEN : 8=PARM
	BSR	GNUM	get mac number
	SUBQ.L	#1,D1
	BNE	MAC_ER82B ---->
	CMPI.B	#')',D0
	BNE	MAC_ER43B ---->
	MOVE.B	D2,D0
	BSR	MAC_GP5	A0 -> parameter, D2 = length
	SUBQ.W	#7,D3
	BEQ	MACP2_3	PLEN
	MOVEM.L	(A7)+,A1-3
	BRA	MACP9_1
MACP9_2	MOVE.B	-(A0),(A2)+
MACP9_1	DBF	D2,MACP9_2
	BRA	MAC_VAL5
;
MAC_ER1B	MOVEQ	#1,D1
MAC_ERZ	MOVEM.L	(A7)+,A1-3
	BRA	MAC_ERY
MAC_ER19B	MOVEQ	#19,D1
	BRA	MAC_ERZ
MAC_ER33B	MOVEQ	#33,D1
	BRA	MAC_ERZ
MAC_ER42B	MOVEQ	#42,D1
	BRA	MAC_ERZ
MAC_ER43B	MOVEQ	#43,D1
	BRA	MAC_ERZ
MAC_ER74B	MOVEQ	#74,D1
	BRA	MAC_ERZ
MAC_ER75B	MOVEQ	#75,D1
	BRA	MAC_ERZ
MAC_ER76B	MOVEQ	#76,D1
	BRA	MAC_ERZ
MAC_ER82B	MOVEQ	#82,D1
	BRA	MAC_ERZ
;
MAC_ER33A	MOVEQ	#33,D1
MAC_ERY	TST.B	IF_SW(A6)
	BEQ	MAC_VAL5
	BSR	DO_ERR
	BRA	MAC_VAL5
;
MAC_ER33	MOVE.W	D1,-(A7)
	MOVEQ	#33,D1
MAC_ERX	TST.B	IF_SW(A6)
	BEQ.S	MAC_ERX1  don't signal error (IF_SW off)
	BSR	DO_ERR
MAC_ERX1	MOVE.W	(A7)+,D1
	BRA	MAC_OX
MAC_ER31	MOVE.W	D1,-(A7)
	MOVEQ	#31,D1
	BRA.S	MAC_ERX
;
; replaces "\0" by the number of parameters
;
MAC_NUM	MOVE.W	#'  ',(A2)+ set no of PARS -> spaces
	MOVEQ	#0,D0
	MOVE.W	([4,A7],-2),D0 no of parameters
	MOVEA.L	A2,A0
	MOVE.W	D1,D6
	BSR	LTOD   set ASCII no of parameters
	MOVE.W	D6,D1
	CMPI.B	#32,(A0)+
	BNE	MAC_OX
	MOVE.B	(A0),-(A2)          only one digit
	BRA	MAC_OX
;
MAC_VI	TST.W	D5
	BNE	MAC_LN5   ~ found - do nothing
	BSR	MAC_LEN
	MOVE.L	D6,D4     set relative pointer to D4
	BRA	MAC_LN5
;
MAC_VO	TST.W	D5
	BNE	MAC_LN5   ~ found - do nothing
	TST.L	D4
	BMI	MAC_ER33  ---->     no "|" yet
	BSR	MAC_LEN
	MOVE.W	D6,D5     set relative pointer to D5
	BRA	MAC_LN5
;
MAC_LEN	MOVE.L	A2,D6
	SUB.L	A3,D6
	RTS
;
MAC_STR	LEA	BUF(A6),A0
MAC_STR3	MOVE.W	(A0)+,D0  length
	BRA	MAC_STR1
MAC_STR2	MOVE.B	(A0)+,(A2)+
MAC_STR1	DBF	D0,MAC_STR2
	RTS
;
DO_INSTR	CMPI.B	#32,(A1)+
	BEQ.S	DO_INSTR
	CMPI.B	#9,-1(A1)
	BEQ.S	DO_INSTR
	CMPI.B	#10,-(A1)
	BEQ	INST_ED1  allow spaces/LF after LABEL
	BSR	SET_PC    keeps position for errors
	BSR	STRGA     allow '.' as a separator
	BMI	PR_E21 ---->
	MOVE.L	D0,D4
	CMPI.B	#32,D0
	BLE.S	INS_OK    TAB, SPACE or ENTER
	CMPI.B	#".",D0
	BNE	PR_E9 ---->
INS_OK	MOVE.W	(A2)+,D1  length of inst
	CMPI.W	#9,D1
	BGT	IN_MACE   might be a MACRO
	LEA	INST_TBLE,A0
	ADDA.W	(A0,D1.W*2),A0
	JMP	(A0)
;
INST_TBLE	DC.W	INST_TW-INST_TBLE
	DC.W	INST_TW-INST_TBLE
	DC.W	INST_TW-INST_TBLE
	DC.W	INST_TH-INST_TBLE
	DC.W	INST_FO-INST_TBLE
	DC.W	INST_FI-INST_TBLE
	DC.W	INST_SI-INST_TBLE
	DC.W	INST_SE-INST_TBLE
	DC.W	INST_EI-INST_TBLE
	DC.W	INST_NI-INST_TBLE
;
; INST_2 = length (Wd) + Insts (Wd)
; INST_3 = length (Wd) + Insts|0 (Long Wd)
; INST_4 = length (Wd) + Insts (Long Wd)
; INST_5 = length (Wd) + Insts|0 (3 Wds)
; INST_6 = length (Wd) + Insts (3 Wds)
; INST_7 = length (Wd) + Insts|0 (2 Long Wds)
; INST_8 = length (Wd) + Insts (2 Long Wds)
; INST_9 = length (Wd) + Insts|0 (5 Wds)
;
; All lists are in reverse order
;
INST_TH	LEA	INST_3,A0
	MOVE.W	(A0)+,D2  no of insts
	MOVE.L	(A2),D3   this inst
	CLR.B	D3
INST_TH1	CMP.L	(A0)+,D3
	DBEQ	D2,INST_TH1
	BNE	IN_MACE ---->
	BRA	INST_THE
;
INST_TW	CMPI.W	#2,D1
	BNE	IN_MACE ---->
	LEA	INST_2,A0
	MOVE.W	(A2),D3
	MOVE.W	(A0)+,D2  no of insts
INST_TW1	CMP.W	(A0)+,D3
	DBEQ	D2,INST_TW1
	BNE	IN_MACE ---->
	BRA	INST_TWE
;
INST_FO	LEA	INST_4,A0
	MOVE.L	(A2),D3
	MOVE.W	(A0)+,D2  no of insts
INST_FO1	CMP.L	(A0)+,D3
	DBEQ	D2,INST_FO1
	BNE	IN_MACE ---->
	BRA	INST_FOE
;
INST_FI	LEA	INST_5,A0
	MOVE.L	(A2),D3
	MOVE.W	(A0)+,D2  no of insts
	MOVE.B	4(A2),D7  inst to D3 & D7
	BRA.S	INST_FI1
INST_FI3	ADDQ.L	#2,A0
INST_FI1	CMP.L	(A0)+,D3
	BNE.S	INST_FI2
	CMP.B	(A0),D7
INST_FI2	DBEQ	D2,INST_FI3
	BNE	IN_MACE ---->
	BRA	INST_FIE
INST_SI	LEA	INST_6,A0
	MOVE.W	(A0)+,D2
	MOVE.L	(A2),D3
	MOVE.W	4(A2),D7
	BRA.S	INST_SI1
INST_SI3	ADDQ.L	#2,A0
INST_SI1	CMP.L	(A0)+,D3
	BNE.S	INST_SI2
	CMP.W	(A0),D7
INST_SI2	DBEQ	D2,INST_SI3
	BNE	IN_MACE   ---->
	BRA	INST_SIE
INST_SE	LEA	INST_7,A0
	MOVE.W	(A0)+,D2  no of 7_insts - 1
	MOVE.L	(A2),D3   1st 4 letters
	MOVE.L	4(A2),D7
	CLR.B	D7        2nd 3 letters + blank
INST_SE2	CMP.L	(A0)+,D3
	BNE.S	INST_SE1  not found
	CMP.L	(A0),D7
INST_SE1	ADDQ.L	#4,A0
	DBEQ	D2,INST_SE2         go on till found
	BNE	IN_MACE   not found ---->
	BRA.S	INST_SEE  7-END
INST_EI	LEA	INST_8,A0
	MOVE.W	(A0)+,D2  no of 8_insts - 1
	MOVE.L	(A2),D3   1st 4 letters
	MOVE.L	4(A2),D7  2nd 4 letters
INST_EI2	CMP.L	(A0)+,D3
	BNE.S	INST_EI1  not found
	CMP.L	(A0),D7
INST_EI1	ADDQ.L	#4,A0
	DBEQ	D2,INST_EI2   go on till found
	BNE	IN_MACE   not found
	BRA.S	INST_EIE  8_END
INST_NI	LEA	INST_9,A0
	MOVE.W	(A0)+,D2  no of 9_insts
	MOVE.L	(A2),D3   1st 4 letters
	MOVE.L	4(A2),D7  2nd 4 letters
	MOVE.B	8(A2),D1  last letter
INST_NI2	CMP.L	(A0)+,D3
	BNE.S	INST_NI1  not this one
	CMP.L	(A0),D7
	BNE.S	INST_NI1  nor this
	CMP.B	4(A0),D1
INST_NI1	ADDQ.L	#6,A0
	DBEQ	D2,INST_NI2
	BNE	IN_MACE   not found
	ADD.W	INST_8,D2
	ADDQ.W	#1,D2
INST_EIE	ADD.W	INST_7,D2
	ADDQ.W	#1,D2
INST_SEE	ADD.W	INST_6,D2
	ADDQ.W	#1,D2
INST_SIE	ADD.W	INST_5,D2
	ADDQ.W	#1,D2
INST_FIE	ADD.W	INST_2,D2
	ADDQ.W	#1,D2
INST_TWE	ADD.W	INST_4,D2
	ADDQ.W	#1,D2
INST_FOE	ADD.W	INST_3,D2
	ADDQ.W	#1,D2
INST_THE	CMPI.W	#2,D2
	BLE	PR_EQ     REG (2), SET (1) or EQU (0)
;
INS_NOM	LEA	PRO_LST,A0
	LSL.W	#3,D2
	ADDA.W	D2,A0
INS_NOM1	MOVEQ	#0,D2     prepare for 'neg' prog no (IF . .)
	MOVE.W	(A0)+,D5
	MOVE.L	(A0)+,D7
	MOVE.B	(A0)+,D2
	CMPI.W	#$FF,D2   ambiguous instruction? . . .
	BEQ	INS_AMB   . . . yes
	MOVE.B	(A0)+,D3
	BMI	QER4      ----> FATAL
	CMPI.B	#NO_SEPS,D3
	BGT	QER4      ----> FATAL
	MOVE.B	D4,D0
	MOVEQ	#-1,D1
	EXT.W	D3
	LEA	INS_TAB,A0
	ADDA.W	(A0,D3.W*2),A0
	JMP	(A0)
;
; Here D7.W = 0 to 4 for the seven ambiguous instructions
;  PTESTR, PFLUSH, PFLUSHA, PMOVE, PTESTW, PLOADR, PLOADW
;
; INS_AMB looks up PTABLE1 given D7.W and bits 1 to 3 of DIP(A6)
; to get the true PRO_LST values.
;
INS_AMB	BFEXTU	DIP(A6){4:3},D0
	MOVE.W	D0,D2
	LSL.W	#3,D0
	SUB.W	D2,D0     7*D0
	ADD.W	D7,D0
	MOVE.B	PTABLE1(D0.W),D0
	BMI	PR_E21    ----> illegal instruction
	EXT.W	D0
	LEA	PTABLE2(D0.W*8),A0
	BRA	INS_NOM1  go back and replace D5, D7, D2
;
PTABLE1	DC.B	0,1,2,-1,11,-1,-1         68040
	DC.B	3,4,5,6,12,14,16          68030
	DC.B	3,4,5,7,12,-1,-1          68EC030
	DC.B	8,9,5,10,13,15,17         68851
;
INS_TAB	DC.W	INS_T0-INS_TAB
	DC.W	INS_T1-INS_TAB
	DC.W	INS_T2-INS_TAB	This sets .S -> .B
	DC.W	INS_T3-INS_TAB
	DC.W	INS_T4-INS_TAB
	DC.W	INS_T5-INS_TAB
	DC.W	INS_T6-INS_TAB
	DC.W	INS_T7-INS_TAB
	DC.W	INS_T8-INS_TAB
	DC.W	INS_T9-INS_TAB
	DC.W	INS_T10-INS_TAB
	DC.W	INS_T11-INS_TAB
	DC.W	INS_T12-INS_TAB
	DC.W	INS_T2-INS_TAB	This sets .S -> .W
;
INS_SPW	MOVEQ	#1,D1     'W'
	BRA.S	INS_SPA
INS_SPL	MOVEQ	#2,D1     'L'
	BRA.S	INS_SPA
INS_SPX	MOVEQ	#13,D1    'X'
INS_SPA	CMPI.B	#".",D0
	BNE.S	INS_SPB
	RTS
;
INS_SPB	ADDQ.L	#4,A7     adjust stack
INS_T0	CMPI.B	#32,D0
	BEQ	INS_SP
	CMPI.B	#9,D0
	BNE	PR_E17 ---->
	BRA	INS_SP
INS_T5	BSR	INS_SPW
INS_T5A	BSR	DO_SIZE
	CMPI.W	#0,D1
	BLE	PR_E16 ---->
	BRA.S	INS_T0
INS_T3	BSR	INS_SPA
	BRA.S	INS_T4A
INS_T4	BSR	INS_SPW
INS_T4A	BSR	DO_SIZE
INS_T4B	BMI	PR_E16 ---->
	BRA	INS_T0
INS_T6	CMPI.B	#32,D0
	BLE	INS_SP    TAB, SPACE or ENTER
	CMPI.B	#".",D0
	BNE	PR_E15 ---->
	BRA.S	INS_T5A
INS_T1	CMPI.B	#10,D0
	BEQ	INS_Q
	CMPI.B	#9,D0
	BEQ	INS_Q
	CMPI.B	#32,D0
	BNE	PR_E9  ---->
	BRA	INS_Q
INS_T2	CMPI.B	#32,D0
	BEQ.S	INS_T2C
	CMPI.B	#9,D0
	BEQ	INS_T2C
	CMPI.B	#".",D0
	BNE	PR_E15
	MOVE.B	(A1)+,D1
	MOVE.B	(A1)+,D0
	CMPI.B	#"S",D1
	BNE.S	INS_T2A
INS_T2B	MOVEQ	#0,D1	-> B
	CMPI.B	#2,D3
	BEQ	INS_T0	Bcc
	MOVEQ	#1,D1	-> W
	BRA	INS_T0	XREF
INS_T2A	CMPI.B	#"s",D1
	BEQ.S	INS_T2B
	SUBQ.L	#2,A1     restore A1
	BRA.S	INS_T4A
INS_T2C	MOVEQ	#3,D1
	BRA	INS_T0
INS_T7	BSR	INS_SPX
	BSR	DO_SIZEF
	BRA	INS_T4B
INS_T8	BSR	INS_SPX
	BSR	DO_SIZEF
	CMPI.B	#2,D1
	BEQ	INS_T0
INS_T8A	CMPI.B	#13,D1
INS_T8B	BEQ	INS_T0
	BRA	PR_E16    ---->
;
INS_T9	BSR	INS_SPA
	BRA	INS_T5A
INS_T10	BSR	INS_SPW
	BSR	DO_SIZEQ
	BRA	INS_T4B
INS_T11	BSR	INS_SPL
	BSR	DO_SIZE
	CMPI.B	#2,D1     'L'
	BRA	INS_T8B
INS_T12	BSR	INS_SPX
	BSR	DO_SIZEF
	BRA	INS_T8A
;
IN_MACE	LEA	BUF(A6),A2
	BSR	NMAC_NO
	BNE	PR_E21 ---->   not a MACRO
	MOVE.W	(A0),D1   set macro number
	MOVE.B	TYPE(A0),D5    max no of pars
	MOVEQ	#31,D2    instruction number
	CMPI.B	#10,-1(A1)
	BNE	INS_SP    more to come
	SUBQ.L	#1,A1	set A1 pointing to LF
INS_SP	CMPI.B	#32,(A1)+
	BEQ.S	INS_SP
	CMPI.B	#9,-1(A1)
	BEQ.S	INS_SP
	SUBQ.L	#1,A1
	MOVE.B	-1(A1),D0
	CMPI.B	#$FC,D2   'RS' or 'EQUR? . .
	BLS	INS_Q     . . no
	MOVE.B	D1,SIZE(A6)
	BRA	PR_EQ
INS_Q	TST.B	D1        .B?
	BNE.S	INS_LB    no
	CMPI.W	#23,D2   DS?
	BEQ.S	INS_LB1   yes
	CMPI.W	#24,D2	DC?
	BEQ.S	INS_LB1   yes
INS_LB	BSR.S	INS_LB3   set PC to even
INS_LB1	MOVE.L	D1,D3
	MOVE.W	MARK(A6),D4
;
;  MARK = 0 for no previous label
;	1 for new label
;	2 for SET label (type 5)
;	4 for XREF label or SET label (wrong type)
;	5 for undetermined label
;
	BEQ.S	INS_LB2   no previous LABEL
	CLR.W	MARK(A6)
	MOVE.W	MARK+2(A6),D1       label no
	BSR	LNPTR     A0 -> LINN
	CMPI.B	#30,D2	MACRO? . .
	BNE	INS_LB6	. . no
	MOVEA.L	A0,A2	set A2 -> LINN
	BRA	INS_LB2
INS_LB6	BTST	#0,D4	0 = error
	BNE.S	INS_LB5	not a SET label or error
	ORI.W	#3,TYPE(A0)
	BRA	PR_E23    ---->
INS_LB5	ORI.W	#6,TYPE(A0)
	MOVE.L	A5,VAL(A0)
	MOVE.W	CRT_SEC(A6),(A0)
INS_LB2	EXG	D3,D1	replace size and set MACRO label no in D3
	BCLR	#7,D2     bit 7 of prog no set for IF insts
	BNE.S	INS_LB4   always obey IF insts
	TST.B	IF_SW(A6)
	BEQ	INST_ED1  don't do instruction if switch OFF
INS_LB4	LEA	PR,A0
	ADDA.L	-4(A0,D2.W*4),A0
	MOVE.L	A5,PC_NOW(A6)       value of *
	ADDQ.L	#2,A5
	MOVE.B	D1,SIZE(A6)         set SIZE
	JMP	(A0)
;
INS_LB3	MOVE.L	A5,D3     PC
	BTST	#0,D3     even?
	BEQ.S	INS_LB3X  yes
	TST.B	D2
	BMI.S	INS_LB3X  don't set (IF's)
	TST.B	IF_SW(A6)
	BEQ	INS_LB3X	don't set (IF switch off)
	BFTST	BRY{D2:1}	if prog no. bit is on don't 'even'
	BNE	INS_LB3X
	ADDQ.L	#1,A5     set to WORD boundary
	ADDQ.L	#1,([PC_TH,A6])           set PC even
	MOVE.W	([PC_TH,A6],4),D3         does this section ..
	CMP.W	([PC_PR,A6],4),D3         .. equal the last? ..
	BEQ.S	INS_LB3Y                  ... yes
	BSET	#6,([PC_TH,A6])	mark ¾
INS_LB3Y	BSR	PUT_B     put byte to _BIN
INS_LB3X	RTS
;
; BRY stops the following instructions from -> even PC
;
;    INST no	Name
;	25	DATA, PCK, PWID, FILETYPE
;	27	Set of QMAC instructions to be ignored
;	30	MACRO, MACROP
;	31	any macro name
;	(52	PWID)
;	84	SECTION, COMMON
;	85	XDEF, XREF
;	86	O_FILE, REL_FILE
;	87	LOW_EA, HIGH_EA, CASE_DIFF, CASE_IND, ERR, LST
;	88	MODULE
;	89	COMMENT
;	92	68040, 68030, 68EC30, 68851
;        106	RS_SET
;        107	ERROR, WARNING
;	
BRY	DC.W	0,$53,0,$800,0,$FC8,$38,0
;
; DO_LAB
;            LABEL layout (for MACROs and SECTIONs too)
;
; All names are divided into three strands by hashing.
; Within a strand each name is held as a one byte length
; followed by the name itself. All names are constrained
; to be no longer than 32 bytes.
;
; Each strand consists of a series of chained 'chunks', each
; of length CHLEN, allocated within a user heap.
;
; The format of the name chunk is:-
;   ______________________________________________________
;  |    FS    |    AC    | len  |<-  name ->|<- etc . . . |
;     (lwd)      (lwd)    (byte)
;
; FS points to the first free space for a name (absolute address)
; AC is the address of the next chunk, or 0 if it is the last.
;
; The first address of each of the three strands is held in three
; long words starting at:
;
;   LAB_LST  for LABELs
;   SEC_LST  for SECTIONs/COMMMONs and
;   MAC_LST  for MACROs
;
;  If an address is zero no chunk has been allocated yet.
;
; A symbol number is made up as 4 times the position in the
; strand plus the strand number (0, 1, or 2).
;
; Information corresponding to a symbol is held in an item 8
; bytes long. The items are held in chunks of size LLEN allocated
; in the same way as name chunks.
;
; The format of an information chunk is:-
;
;  _______________________________________________
; |   AC   | spare |<   item    >|<  etc  ....    |
;   (lwd)    (lwd)    (8 bytes)
;
; AC is the address of the next chunk (0 if none)
;
; Each item is:-
;
;  __________________________________
; |  num  |     value       |  type  |
;    (wd)       (lwd)          (wd)
;
; Num is -2 to signal the 1st free item in the chunk. Otherwise
; the meaning of the contents depends on the type of symbol.
;
; For LABELs num is zero unless it is of PC type when num is the
; section number (-1, 0, 1, etc).
;
; For SECTIONs/COMMONs/ORGs num is the section number (as for LABELs)
; and type is 0, 1, 2 for SECTIONs/COMMONs/ORGs. Value is unused for
; SECTIONs/COMMONs but is 'k' for ORGs. 'k' is the PC setting at the
; start of that particular ORG.
;
; For MACROs num is the macro number and the rest of the item is unused.
;
; For LABELs:
;
;   Value is the value of the label whether PC or scalar or
;         is the address of 1) an EQU list or
;                           2) an entry in the FP_LST,
;                              STR_LST or QUD_LST
;
;    XREF value is its <id> in bits 0 - 15 (inserted @ PASS2)
;
;   Type - bits 4-5 indicate  'normal' if 0 and FP, 1 Quad, 2  String 3
;         -bit 6    indicates 'normal' if 0 and SET if 1
;
;         for normal labels bits 0 - 1 have the meaning:
;                               0     unknown
;                               1     N (a scalar number)
;                               2     PC
;                               3     Error
;
;                           bits 2 - 3 have the meaning
;                               0    awaiting definition
;                               1    defined
;                               2    EQU list
;
;         for FP or String labels bits 4 - 5 have the meaning
;                               1    FP
;                               2    Quad word
;                               3    String
;
;         for XDEF & XREF labels bits 12 - 15 are used:
;                 bits 12- 13 = 1 for XDEF & 2 for XREF
;                 for XREF labels bits 14 - 15 indicate
;                      0 = B, 1 = W, 2 = L
;
;          REG labels have type $105 and EQUR labels $205
;
DO_LAB	TST.B	IF_SW(A6)
	BEQ	INST_ED1  ignore label
	BSR	SET_PC    keep position in case of error
	BSR	STRG
	BMI	PR_E6 ---->
	CMPI.W	#32,(A2)
	BLE.S	DO_LAB1
	MOVE.W	#32,(A2)  set len <= 32
	BSR	PR_W4     truncation warning
DO_LAB1	CMPI.B	#32,D0
	BLE	DO_LAB2
	CMPI.B	#":",D0
	BNE	PR_E9 ---->
DO_LAB2	MOVE.B	D0,D4     keep D0.B
	LEA	D_LIST,A0
	MOVEQ	#19,D1
	MOVE.L	A1,-(A7)
	MOVEA.L	A2,A1
	BSR	FIND1
	MOVEA.L	(A7)+,A1
	TST.W	D1
	BPL	PR_E20 ---->
	BSR	NLAB_NO
	BEQ.S	IN_LIST
	BSR	NNEW_LAB
	MOVEQ	#1,D0     for ordinary MARK
	BRA.S	IN_OK
IN_LIST	MOVE.W	TYPE(A0),D2
	MOVEQ	#1,D0     for ordinary MARK
	BTST	#13,D2    XREF . . .
	BEQ	IN_LIST1	. . . no
IN_LIST3	MOVEQ	#4,D0 	signal an error (unless MACRO)
	BRA	IN_OK1
;
IN_LIST1	MOVE.W	D2,D3
	ANDI.W	#12,D2
	BNE	IN_LIST2	label determined
	MOVEQ	#5,D0	mark old undetermined label
	BRA	IN_OK     (LAB not determined)
;
IN_LIST2	BTST	#6,D3     SET type label? . . .
	BEQ	IN_LIST3	. . . no
	ANDI.W	#7,D3
	CMPI.W	#5,D3
	BNE	IN_LIST3  can't SET this
	MOVEQ	#2,D0     for MARK
IN_OK	TST.W	MARK(A6)
	BEQ.S	IN_OK1    No immediately preceding LABEL
	MOVE.L	D1,D3
	MOVEQ	#12,D1
	MOVE.L	D0,-(A7)
	BSR	NN_LG2    get 12 bytes
	MOVE.L	(A7)+,D0
	MOVEA.L	A0,A3
	MOVE.W	MARK+2(A6),D1   LAB1 no
	BSR	LNPTR     A0 -> LINN
	MOVE.L	D3,D1
	EXG	A0,A3
	MOVE.L	A0,VAL(A3) set EQ pointer to VAL
	CLR.L	(A0)+     constant -> 0
	CLR.W	(A0)+     S(PC) -> 0
	MOVE.W	#1,(A0)+  sign -> +
	MOVE.W	D1,(A0)+  No of LAB2
	ORI.W	#$A,TYPE(A3) LAB type to PC/EQ list
	CLR.W	(A0)+     mark end of EQ list
IN_OK1	MOVE.W	D1,2+MARK(A6)  set LAB2 no to MARK+2
	MOVE.W	D0,MARK(A6)         set 1 or 2
	CMPI.B	#10,D4    is separator ENTER?
	BEQ	INST_ED1  yes
	BRA	DO_INSTR
;
; PASS2 (preceded by IN_END)
;
; IN_END unwinds the nesting of IN'd files
;   _________     _________     ________________________     ________
;  |_________|\  | CH_LST  |   |       CHM_LST           |  |________|
;    CH_IN     \ |         |   |            |            |   CHM_NO
;   _____       \|_________|   |____________|____________|  /
;  |_____|-----> |1|       |-->|MAC no|Ident|  File pos  | /
;   CH_NO        |---------|   |-------------------------|/ end of list
;                |_________|   |_________________________|
;
IN_END	MOVE.W	CH_NO(A6),D4    more IN's? . .
	BNE.S	IN_END1         . . yes
	MOVEQ	#0,D2     set D2.B > 0 for INS_LB3
	BSR	INS_LB3   set PC even
	BSR	ST_LNO    to next line (twice)
	BSR	ST_LNO
	MOVE.L	A5,D0
	ADD.L	D0,([PC_PR,A6])
	MOVE.W	CRT_SEC(A6),([PC_PR,A6],4)
	ADD.L	D0,([PC_TH,A6])
	MOVE.W	CRT_SEC(A6),([PC_TH,A6],4)
	BRA	PASS2
IN_END1	SUBQ.W	#1,CH_NO(A6)   previous IN file
	MOVE.L	CH_IN(A6),D0
	BPL.S	IN_END2        not a MACRO
	BCLR	#31,D0
	MOVEA.L	(A7)+,A6  recall pointer
	UNLK	A6        release parameter space
	MOVE.W	CHM_NO(A6),D7
	SUBQ.W	#1,CHM_NO(A6)
	MOVE.W	([CHM_LST,A6],D7.W*8,-8),D5  MACRO no
	SUBQ.W	#2,D7
	BMI	IN_END5   do CLOSE and release 'P' space
IN_END4	CMP.W	([CHM_LST,A6],D7.W*8),D5 is MACRO still open?
	DBEQ	D7,IN_END4               .................
	BNE	IN_END2                  .. no
	MOVEQ	#-1,D3
	MOVE.L	([CHM_LST,A6],D7.W*8,4),D1  position of file
	MOVEQ	#FS_POSAB,D0
	TRAP	#3
	BRA	IN_END3                  don't CLOSE
;
IN_END5	MOVE.L	D0,D7
	BSR	PR31_PL		pointer to 'P' chain
	MOVEA.L	A0,A1
	MOVEA.L	4(A1),A0		address of MACL area . .
	CLR.L	4(A1)
	MOVE.L	-(A0),D1		. . and its length
	LEA	HEAPAD(A6),A1
	MOVEA.W	MM_LNKFR,A2
	JSR	(A2)
	MOVE.L	D7,D0
IN_END2	MOVEA.L	D0,A0
	MOVEQ	#IO_CLOSE,D0
	TRAP	#2        close current IN file
IN_END3	MOVE.L	([CH_LST,A6],D4.W*4,-4),CH_IN(A6) next CH_IN
	BRA	GLIN1     and assemble it
;
	IN	@"RAM1_",TITLE,"_1A_ASM"
	IN	@"RAM1_",TITLE,"_2_ASM"
	IN	@"RAM1_",TITLE,"_3_ASM"
	IN	@"RAM1_",TITLE,"_4_ASM"
	IN	@"RAM1_",TITLE,"_5_ASM"
	IN	@"RAM1_",TITLE,"_6_ASM"
