Google
 

Trailing-Edge - PDP-10 Archives - steco_19840320_1er_E35 - 10,5676/teco/source/mac.mac
There are 3 other files named mac.mac in the archive. Click here to see a list.
	SUBTTL	Nick Bush/NB, Robert McQueen/RCM/SSG/RH
	SUBTTL	Preamble
; Copyright (c) 1979 by
; Stevens Institute of Technology, Hoboken, New Jersey, 07030
; All rights reserved.
;
; This software is furnished under a license and may be used and copied
; only in accordance with the terms of such license and with the
; inclusion of the above copyright notice.  This software or any other
; copies thereof may not be provided or otherwise made available to any
; other person.  No title to or ownership of the software is hereby
; transferred.
;
;
; The information in this software is subject to change without notice
; and should not be construed as a commitment by Stevens Institute of
; Technology.
;
 
; Version number
 
	MACVER==1		; Major version
	MACMIN==0		; Minor version
	MACEDT==41		; Edit number
	MACWHO==0		; Who last edited
 
 
; Directives
 
IFNDEF %%.BIN,.DIREC	.NOBINARY	; No binary output
	SALL			; Suppress macro expansions
	SUBTTL	Table of Contents

;+
;.pag.lit

;		Table of Contents for MAC - DECsystem-10 Common parameter file
;
;
;			   Section			      Page
;   1. Preamble . . . . . . . . . . . . . . . . . . . . . . .    1
;   2. Table of Contents. . . . . . . . . . . . . . . . . . .    2
;   3. Revision History . . . . . . . . . . . . . . . . . . .    3
;   4. Macro definitions
;        4.1.   TITLE. and friends. . . . . . . . . . . . . .    4
;        4.2.   BUILD$. . . . . . . . . . . . . . . . . . . .    6
;        4.3.   MODSHW macro. . . . . . . . . . . . . . . . .    8
;   5. Identity of the program. . . . . . . . . . . . . . . .    9
;   6. Macro definitions
;        6.1.   DELTTL. . . . . . . . . . . . . . . . . . . .   10
;   7. Interesting symbols. . . . . . . . . . . . . . . . . .   11
;   8. Macro definitions
;        8.1.   ND, XP, EXT, GLOB . . . . . . . . . . . . . .   12
;        8.2.   Byte manipulation . . . . . . . . . . . . . .   14
;        8.3.   PG2ADR & ADR2PG . . . . . . . . . . . . . . .   16
;        8.4.   .CONS . . . . . . . . . . . . . . . . . . . .   17
;        8.5.   ..TSAC - Test to see if an AC . . . . . . . .   18
;        8.6.   PUSH. and POP.. . . . . . . . . . . . . . . .   18
;        8.7.   STORE - Store a value into memory . . . . . .   19
;        8.8.   MOVX. . . . . . . . . . . . . . . . . . . . .   20
;        8.9.   CAX?. . . . . . . . . . . . . . . . . . . . .   21
;        8.10.  TX??. . . . . . . . . . . . . . . . . . . . .   22
;        8.11.  ADDX, SUBX, and etc.. . . . . . . . . . . . .   23
;        8.12.  Floating point (FADRX, etc) . . . . . . . . .   25
;        8.13.  Structure control
;             8.13.1.    INTSTR, etc. . . . . . . . . . . . .   26
;             8.13.2.    DEFST. . . . . . . . . . . . . . . .   29
;             8.13.3.    $SET, $BUILD, and $EOB . . . . . . .   30
;             8.13.4.    LOAD . . . . . . . . . . . . . . . .   31
;             8.13.5.    LOAD.. . . . . . . . . . . . . . . .   32
;             8.13.6.    LOADS. . . . . . . . . . . . . . . .   33
;             8.13.7.    LOADE. . . . . . . . . . . . . . . .   34
;             8.13.8.    STOR . . . . . . . . . . . . . . . .   35
;             8.13.9.    STOR.. . . . . . . . . . . . . . . .   36
;             8.13.10.   STORS. . . . . . . . . . . . . . . .   37
;             8.13.11.   STORI. . . . . . . . . . . . . . . .   38
;             8.13.12.   ZERO.. . . . . . . . . . . . . . . .   39
;             8.13.13.   ONES.. . . . . . . . . . . . . . . .   40
;             8.13.14.   INCR.. . . . . . . . . . . . . . . .   41
;             8.13.15.   DECR.. . . . . . . . . . . . . . . .   42
;             8.13.16.   CFMxx. . . . . . . . . . . . . . . .   43
;             8.13.17.   CFXxx. . . . . . . . . . . . . . . .   44
;        8.14.  LSTOF. and LSTON. . . . . . . . . . . . . . .   45
;        8.15.  INTFLG & FLAG . . . . . . . . . . . . . . . .   46
;        8.16.  INTNUM & NUM. . . . . . . . . . . . . . . . .   47
;        8.17.  .BIT. . . . . . . . . . . . . . . . . . . . .   48
;        8.18.  .INT. . . . . . . . . . . . . . . . . . . . .   49
;        8.19.  BITMSK. . . . . . . . . . . . . . . . . . . .   50
;        8.20.  TABDEF, TABENT, TABEND. . . . . . . . . . . .   51
;        8.21.  BITON & BITOFF. . . . . . . . . . . . . . . .   52
;        8.22.  Stack control (FRAME.). . . . . . . . . . . .   53
;        8.23.  JUMPPT. . . . . . . . . . . . . . . . . . . .   54
;   9. Useful OPDEFS. . . . . . . . . . . . . . . . . . . . .   55
;  10. Symbols for the control characters . . . . . . . . . .   56
;  11. Hardware bits of interest to users . . . . . . . . . .   57
;  12. End of MAC . . . . . . . . . . . . . . . . . . . . . .   58

;.end lit.pag
;-
	SUBTTL	Revision History
 
COMMENT	|
 
Start of version 1.
 
1	Merge the good parts of STRDEF, and MACTEN.  Redefine most
	of the MACTEN macros so they are always useful.

2	Insert STORS.
3	Fix several problems with items not being .XCREF'd
4	Change BITMSK definition to take a symbol prefix
5	Fix BYT when it has a non-zero position.
6	Fix TITLE. to avoid getting nulls in the various expansions.
7	Fix ENDSTR to do a DEFSM. for the length symbol, so that
	the user gets informed of an error.
10	Add the signed/unsigned attribute to DEFST. and add the
	CFXxx. macros.
11	Fix the store macro to handle the case where the caller
	gives a last location but it is the same as the first.
12	Add $BUILD, $SET, $EOB macros to build resident data structures
	using the structure definition macros.
13	Put STORE back the way it was....edit 11 breaks too many things
14	Fix ..IFDEF and ..IFNDEF to really work. They don't need angle
	brackets around the argument.
15	Add the FALL macro definition.  This allows falling from one
	routine to the next.
16	Use $$$VAL in the $SET routine.
17	Fix double word compares.
	Don't allow MDF symbols to be defined with the FLAG and NUM macros.
	Check to see if the symbols are defined on pass one before defining.
20	Fix the HALF macro for structures
21	Fix TITLE. in case caller has a comma in his text argument
22	Make PSECTs work.  Symbols migrate from one symbol table to another
	if they are .XCREF'd.  So PURGE the death out of $$$VAL in hopes to
	prevent the wrong PSECT index from showing up in the REL file for
	polish expressions (TECO %200 has problems with this).
23	Make TABENT work with odd expressions as the VALUE argument. This
	makes it possible to use $BUILD to build the work for the
	value.
24	Fix a bug in CFXxx macros.
25	Add .CHxxx symbols for the ASCII control character names. For those
	that already had the correct xxx (ie .CHBEL) add the corresponding
	.CHCxx symbol (.CHCNG).
26	Define BP.SIZ and BP.POS to maintain compatiblity with the rest of
	the world. These are fields in byte pointers.
27	Make sure that the POINTR macro does not generate polish.  This
	messes up SITGO.
30	Avoid printing error message if DEFSM. is redefining a symbol to a
	value it already has.
31	Add $SETFL to set flags using the structure definition macros.
32	Change the GLOB macro to do a .IF symbol,LOCAL instead or a
	IFDEF check before making the symbol internal
33	Fix TX.. macro for TXNN case when the value has -1 for a left half.
34	Change LIW to IFIW (Instruction format indirect word).
35	Define an ENDNUM macro to define the MAX symbol for the INTNUMs.
36	Enhance the FRAME. macro to have the same functionality as the
	STKVAR macro in GLXMAC.
37	Add symbols for length of the character mask, and the number of bits
	used per word in the mask.
40	Remove a few of the PURGEs.  Symbols don't move around in symbol
	tables as bad as DEC thought.  This allows them to be .XCREF'd.
41	Fix STORI. to handle relocatable and external symbols as the value to
	store.
|
	SUBTTL	Macro definitions -- TITLE. and friends
 
 
 
;+.CENTER
;TITLE. macro
;.SKIP 2
;The TITLE. macro is designed to handle the problems of
;maintaining version numbers in programs.  The macro generates
;a series of macros to preform various functions for the
;MACRO-10 programmer.  The general form is:
;.PARAGRAPH 0
;TITLE. (ABV,PRGNAM,COMMENT)
;.TAB STOPS 8
;.LEFT MARG 8
;.PARAGRAPH -8
;Where: ABV=3-Character program abbreviation, ie. "DRT" for DIRECT.
;.BREAK
;PRGNAM=Program name, DIRECT.
;.BREAK
;COMMENT=Short statement stating program's function
 
;.LEFT MARG 0
;.PARA 0
;The TITLE. macro assumes that four symbols are defined,
;XXXVER, XXXMIN, XXXWHO and XXXEDT, where XXX=the 3-character
;program abbreviation supplied to the macro.
;Two symbols are defined XXXASC and XXXSIX which are symbolically
;and respectively defined as the ASCII and SIXBIT values of the
;program abbreviation supplied.
;-
;&.SUBTTL TITLE MACRO
 
 
; TITLE. (DRT,DIRECT,PROGRAM TO LIST DIRECTORIES)
DEFINE TITLE.(ABV,PRGNAM,COMENT),<
	.XCREF
	...Z==0
	IFNDEF ABV'VER,<...Z==-1>
	IFNDEF ABV'MIN,<...Z==-1>
	IFNDEF ABV'EDT,<...Z==-1>
	IFNDEF ABV'WHO,<...Z==-1>
	IFL ...Z,<PRINTX ?Symbols ABV'WHO,ABV'VER,ABV'MIN and ABV'EDT not defined
	PRINTX ?Version symbols must be defined before calling TITLE. macro
END>
	.CREF
	IF2,<LALL>
	ABV'SIX==SIXBIT /ABV/	; PRGNAM abbreviation in SIXBIT
	ABV'ASC==ASCIZ /ABV/	; PRGNAM abbreviation in ASCII
	SALL
	.XCREF
%FIRST=ABV'MIN/^D26
IFE %FIRST,<%SECON==ABV'MIN
	%FIRST==0>
IFG %FIRST,<%SECON=ABV'MIN-<^D26*%FIRST>>
IFE ABV'MIN-^D26,<%SECON==ABV'MIN
	%FIRST=0>
IFE ABV'MIN-^D52,<%SECON==^D26
	%FIRST=1>
	IFG	ABV'MIN-77,<
PRINTX ? Minor version number too large - ignoring it
	ABV'MIN==0
	%SECOND==0
	%FIRST==0
>
IFN %FIRST,%FIRST==%FIRST+"A"-1
IFN %SECOND,%SECOND==%SECOND+"A"-1
; DEFINE ALL THE MACROS
IFN %FIRST,IFN %SECOND,BUILD$ (PRGNAM,\ABV'VER,\ABV'MIN,\"%FIRST,\"%SECON,\ABV'EDT,\ABV'WHO,<COMENT>,ABV)
IFE %FIRST,IFE %SECOND,BUILD$ (PRGNAM,\ABV'VER,\ABV'MIN,,,\ABV'EDT,\ABV'WHO,<COMENT>,ABV)
IFE %FIRST,IFN %SECON,BUILD$ (PRGNAM,\ABV'VER,\ABV'MIN,,\"%SECON,\ABV'EDT,\ABV'WHO,<COMENT>,ABV)
 
	IF2,<PURGE %SECON,%FIRST,...Z>
.CREF>
	SUBTTL	Macro definitions -- BUILD$

;+The TITLE. macro generates the following macros to
;be optionally called by the user.
;.LEFT MARG 8
;-.TAB STOPS 8
 
DEFINE BUILD$ (PRGNAM,MAJN,MINOR,L1,L2,EDIT,CUS,COMENT,ABV),<
 
;+.PARA -8
;XXXTTL	Macro to generate a TITLE statement of the form:
;.BREAK
;-TITLE PRGNAM COMMENT VERSION
	DEFINE ABV'TTL,<IFG CUS,<
	TITLE	PRGNAM - COMENT  %'MAJN'L1'L2(EDIT)-CUS
>IFE CUS,<
	TITLE	PRGNAM - COMENT  %'MAJN'L1'L2(EDIT)
>>
 
;+.PARA -8
;XXX137	Macro to setup location 137 with the specified
;-version number. Note: the macro does its own "LOC" and "RELOC".
	DEFINE ABV'137,<IFG CUS,<
	IF2,<LALL>
	LOC	137
	BYTE (3)ABV'WHO(9)ABV'VER(6)ABV'MIN(18)ABV'EDT	; PRGNAM %'MAJN'L1'L2(EDIT)-CUS
	RELOC
	SALL
>	IFE CUS,<
	IF2,<LALL>
	LOC	137
	BYTE (3)ABV'WHO(9)ABV'VER(6)ABV'MIN(18)ABV'EDT	; PRGNAM %'MAJN'L1'L2(EDIT)
	RELOC
	SALL
>>
 
; Macro to define version # at current location
;+.PARA -8
;XXXVRS	Macro to define the version number at an
;-arbitrary user location.
	DEFINE ABV'VRS,<IFG CUS,<
	IF2,<LALL>
	BYTE (3)ABV'WHO(9)ABV'VER(6)ABV'MIN(18)ABV'EDT	; PRGNAM %'MAJN'L1'L2(EDIT)-CUS
	SALL
>	IFE CUS,<
	IF2,<LALL>
	BYTE (3)ABV'WHO(9)ABV'VER(6)ABV'MIN(18)ABV'EDT	; PRGNAM %'MAJN'L1'L2(EDIT)
	SALL
>>
 
; Generate a PASS2 PRINTX statement
;+.PARA -8
;-XXXPTX	Generates a pass 2 PRINTX statement.
	DEFINE ABV'PTX,<
	IF2,<
	IFG CUS,<PRINTX PRGNAM %'MAJN'L1'L2(EDIT)-CUS	COMENT
>	IFE CUS,<PRINTX PRGNAM %'MAJN'L1'L2(EDIT)	COMENT
>>>
 
;+.PARA -8
;XXXUNV	Macro to generate a UNIVERSAL statement. The macro in
;effect is an exact copy of the XXXTTL macro except that the
;-word "UNIVERSAL" replaces the word "TITLE".
	DEFINE ABV'UNV,<IFG CUS,<
	UNIVERSAL PRGNAM - COMENT  %'MAJN'L1'L2(EDIT)-CUS
>IFE CUS,<
	UNIVERSAL PRGNAM - COMENT  %'MAJN'L1'L2(EDIT)
>>
 
;+.PARA -8
;XXXERR	Macro to type a fatal error message on the
;user's terminal. The call is of the form:
;.BREAK
;XXXERR (ZZZ,Error message,<PDP-10 instruction>)
;.BREAK
;ZZZ is the 3-character error code, error message is the ASCIZ
;string to be typed on the terminal and PDP-10 instruction is
;an optional argument indicating what the user wants to do
;about the error just typed. If the argument is null an
;-EXIT is executed.
	DEFINE ABV'ERR (COD,MSG,INSTR),<
ABV''COD:	JRST	[
	OUTSTR	[ASCIZ \
? ABV''COD MSG\]
	IFNB <INSTR>,<INSTR>
	IFB <INSTR>,<EXIT>
]>
 
;+.PARA -8
;XXXWRN	Macro similar to the XXXERR macro except that a
;warning message is issued rather than a fatal and
;-the default PDP-10 instruction to be executed is "JRST .+1".
	DEFINE ABV'WRN (COD,MSG,INSTR),<
ABV''COD:	JRST	[
	OUTSTR	[ASCIZ \
% ABV''COD MSG\]
	IFNB <INSTR>,<INSTR>
	IFB <INSTR>,<JRST .+1>
]>
 
;+.PARA -8
;XXXNME	Macro to call another macro with the version number as an argument.
;This macro is given the name of another macro to call with the ASCII version
;number as the only macro argument.
;-
 
	DEFINE	ABV'NME(MCRNME)<
IFG CUS,<
	MCRNME'(<%'MAJN'L1'L2(EDIT)-CUS>)
>
IFE CUS,<
	MCRNME'(<%'MAJN'L1'L2(EDIT)>)
>>
 
;; DEFINE NEW MACROS HERE
>
	SUBTTL	Macro definitions -- MODSHW macro
 
;+
;.SKIP 2
;.LEFT MARG 0
;.CENTER
;MODSHW macro
;.PARA 0
;The MODSHW macro is designed to "show" version values of related
;modules. The form is "MODSHW (ABV)" where ABV is the 3 character
;program abbreviation. The symbol "%%ABV" is defined with that value.
;-
 
	DEFINE MODSHW (ABV),<
	LALL
	%%'ABV==VRSN.(ABV)
	SALL
>
	SUBTTL	Identity of the program
 
	TITLE.	(MAC,MAC,<DECsystem-10/20 common parameter file>)
	MACUNV			; Generate the universal statement
	MACPTX			; Generate the printx
	SUBTTL	Macro definitions -- DELTTL
 
;+
;.HL2 DELTTL
; This macro will delete all the macros that were generated by the
;TITLE. macro.
;-
 
DEFINE	DELTTL(ABV),<
	IF2,<
		PURGE	ABV'TTL,ABV'ERR,ABV'WRN,ABV'NME,ABV'PTX
		PURGE	ABV'137,ABV'UNV,BUILD$,ABV'VRS
	>; End of IF2
>; End of DELTTL definition
	SUBTTL	Interesting symbols
 
; Version format components
 
VR.WHO==7B2			; Who editted (0-DEC development, 1-Other DEC,
				; 2 to 4 - Customer, 5 to 7 End user)
VR.VER==777B11			; Major version number
VR.MIN==77B17			; Minor version number
VR.EDT==777777			; Edit level
 
; Macro to format this module's version
;	VRSN.	PREFIX
 
; Assumes symbols in the form of PREFIX'WHO,PREFIX'VER,...
 
DEFINE VRSN.(PFX),<BYTE (3)PFX'WHO (9)PFX'VER (6)PFX'MIN (18)PFX'EDT>
 
 
;Instruction Word masks
 
IW.OPC==777B8			; Mask for the opcode
IW.REG==17B12			; Mask for the register
IW.IND==1B13			; Mask for the indirect bit
IW.IDX==17B17			; Mask for the index register
IW.ADR==0,,-1			; Mask for the address
	IW.PAG==777B26		; Mask for page number within address field
	IW.OFF==777B35		; Mask for offset within page
 
; Masks for global indirect word fields
 
GW.ZER==1B0			; Sign bit must be zero
GW.IND==1B1			; Indirect bit
GW.IDX==17B5			; Index register
GW.ADR==7777777777B35		; Address field
	GW.SEC==7777B17		; Section number
	GW.PAG==777B26		; Page number within section
	GW.OFF==777B35		; Offset within page

; Byte pointer fields

BP.PFL==77B5			; Position field
BP.SFL==77B11			; Size field
BP.GLB==1B12			; Bit saying this is really global byte pointer
BP.POS==77B5			; New definition for position field
BP.SIZ==77B11			; New definition for size field

 
; Misc. constants
 
.INFIN==377777,,777777		; Plus infinity
.MINFI==1B0			; Minus infinity
LH.ALF==777777B17		; Left half word mask
RH.ALF==777777			; Right half word mask
FW.ORD==-1			; Full word mask
.ZERO5==0			; Mnemonic that no @ or index possible
	SUBTTL	Macro definitions -- ND, XP, EXT, GLOB
 
; Macro to define a symbol if not already defined
;	ND  SYMBOL,VALUE
 
DEFINE	ND(SYMBOL,VALUE),<
	IFNDEF	SYMBOL,<SYMBOL==VALUE>
>
 
 
; Macro to show the value of an absolute symbol
;	SHOW	SYMBOL
; Warning -- Do not use as the last location in a segment
 
DEFINE	SHOW.(ARG$),<	.XCREF
	EXP	<ARG$>
	.ORG	.-1
			.CREF>
 
 
; Macro to define a symbol if not already defined and show its value
; Warning -- Do not use as last location in a segment
 
DEFINE	NDS.(SYMBOL,VALUE),<
	IFNDEF	SYMBOL,<SYMBOL==VALUE>
	SHOW.	(SYMBOL)
>
 
 
;+
;.hl2 NDSI.
; This macro is the same as the NDS. macro, except that it will internal
;the symbol so that LINK will complain about differing values.
;-
 
DEFINE	NDSI.(SYMBOL,VALUE),<
	NDS.	SYMBOL,<VALUE>
	INTERN	SYMBOL
>; End of NDSI. definition
; Macro to define a symbol and force it internal
;	XP  SYMBOL,VALUE,PRINT
;		Where print is non-blank to print out from DDT
 
DEFINE	XP(SYMBOL,VALUE,PRINT),<
	INTERN	SYMBOL
	IFB  <PRINT>,<SYMBOL==VALUE>
	IFNB <PRINT>,<SYMBOL=VALUE>
>
 
 
; Macro to extern a symbol if not defined in this routine
;	EXT	SYMBOL
 
DEFINE	EXT(SYMBOL),<
	IRP	SYMBOL,<
	IF2,<	IFNDEF	SYMBOL,<EXTERN SYMBOL> >>>
 
 
 
; Macro to extern of intern a list of symbols
;	GLOB	SYMBOL
 
DEFINE	GLOB(SYMBOL),<
	IRP	SYMBOL,<
	IF2,<	.XCREF
		.IF SYMBOL,LOCAL,<INTERN SYMBOL>
		.IF SYMBOL,NEEDED,<EXTERN SYMBOL>
		.CREF
>>>
	SUBTTL	Macro definitions -- Byte manipulation
 
;Macro to compute the width of a mask
;	"WID" returns the length of the leftmost string of
;	consecutive ones in the word.
 
DEFINE	WID(MASK),<<^L<-<<MASK>_<^L<MASK>>>-1>>>
 
;Macro to compute the position of a mask
 
DEFINE	POS(MASK),<<^L<MASK>+^L<-<<MASK>_<^L<MASK>>>-1>-1>>
 
;Macro to build a pointer to a masked quantity
;	POINTR	LOCATION,MASK
 
DEFINE	POINTR(LOC,MASK),<POINT WID(MASK),LOC,POS(MASK)>
 
;Macro to build a mask "WID" bits wide, with its rightmost bit
;	in the bit position "POS".  (i.e. a mask for the byte
;	pointed to by the byte pointer "POINT WID,LOC,POS")
 
DEFINE	MASK.(WID,POS),<<<<1_<WID>>-1>B<POS>>>
 
;Macro to define a symbol with only one bit on, in the same position as
;	the rightmost bit in "MASK" (or 0 if "MASK" = 0)
 
DEFINE RGHBT.(MASK),<<<MASK>&-<MASK>>>
 
;Macro to define a symbol with only one bit on, in the same position as
;	the leftmost bit in "MASK" (or 0 if "MASK" = 0)
 
DEFINE LFTBT.(MASK),<<1B<^L<MASK>>>>
 
;Macro to return a word with consecutive string of ones from the
;	bit position of the leftmost bit inn "MASK" through the bit position
;	of the rightmost one in "MASK" inclusive.
 
DEFINE FILIN.(MASK),<<<MASK>!<<LFTBT.(MASK)>-<RGHBT.(MASK)>>>>
 
; ALIGN. returns the number of trailing zeros in "MASK".
;	(i.e. a value which is the right counterpart of the value
;	returned by the MACRO-10 operator "^L")
 
DEFINE ALIGN.(MASK),<<^D35-<^L<RGHBT.(MASK)>>+<^D37*<<^L<RGHBT.(MASK)>>/^D36>>>>
 
; BTSWP.(AC,BIT1,BIT2) swap the bits 1 and 2 in the AC.
;	BIT1 and BIT2 are decimals 0 to 35
 
DEFINE	BTSWP.(AC,BIT1,BIT2),<
	REPEAT	3,<
	TXCE	AC,1B<BIT1>!1B<BIT2>
>>
 
; INSVL. positions value in mask
 
DEFINE INSVL.(VALUE,MASK),<<<<VALUE>B<POS(<MASK>)>>&<MASK>>>
	SUBTTL	Macro definitions -- PG2ADR & ADR2PG
 
;+
;.HL1 PG2ADR
; This macro will convert a page number in the specified AC
;to an address in the AC.  This macro has only one argument and
;that is the AC that contains the page number.
;-
 
 
DEFINE	PG2ADR(AC),<
	IFE ..TSAC(AC),<PRINTX ? AC is not a register in PG2ADR>
	LSH	AC,^D9
>; End of PG2ADR definition
 
;+
;.HL1 ADR2PG
; This macro will convert the address in a specified AC
;to the page number of the address.  This macro has only one argument
;which is the AC containing the address.
;-
 
DEFINE	ADR2PG(AC),<
	IFE ..TSAC(AC),<PRINTX ? AC is not a register in ADR2PG>
	LSH	AC,-^D9
>
	SUBTTL	Macro definitions -- .COND
 
;+
;.HL1 _.COND
; This macro will act like the LISP COND function.  It
;accepts a list of condition-action pairs.
;-
 
 
DEFINE	.COND(LIST),<
	IRP <LIST>,<
		IFN <COND.. LIST >,<
			CON... LIST
			STOPI
		>
	>
	.XCREF	COND..,CON...,...CON,..COND,.COND
>; End of .COND definitions
 
DEFINE	COND..(ITEM),<..COND ITEM >
DEFINE	..COND(COND,INSTRUCTIONS)<IFE <COND>,<-1>>
 
DEFINE	CON...(LIST),<...CON LIST >
DEFINE	...CON(COND,INSTRUCTIONS)<
		INSTRUCTIONS
>
 
; Some condtional macros for .COND
 
DEFINE ..DF(LIST),<IRP <LIST>,<...DF LIST>>
DEFINE ...DF(LIST),<....DF LIST>
DEFINE ....DF(TYP1,TYP2),<
	DEFINE ..IF'TYP1(ARG),<IF'TYP2 <ARG>,<-1>>
	DEFINE ..IF'TYP2(ARG),<IF'TYP1 <ARG>,<-1>>
>
 
 
..DF(<<E,N>,<GE,L>,<G,LE>,<B,NB>>)
	PURGE	..DF,...DF
 
DEFINE ..IFDEF(ARG1),<IFNDEF ARG1,<-1>>
DEFINE ..IFNDEF(ARG1),<IFDEF ARG1,<-1>>
DEFINE ..IFIDN(ARG1,ARG2),<IFDIF <ARG1>,<ARG2>,<-1>>
DEFINE ..IFDIF(ARG1,ARG2),<IFIDN <ARG1>,<ARG2>,<-1>>
	SUBTTL	Macro definitions -- ..TSAC - Test to see if an AC
 
;+
;.hl2 ..TSAC
; This is a support macro for the structure processing.  This macro will
;test to see if the address part of the field is an AC.  This macro will
;return a 0 if it is not and a 1 if it is
;-
 
DEFINE	..TSAC(ADDR),<.IF ADDR,ABSOLUTE,<IFE <<<ADDR>&17>-<ADDR>>,<-1>>>
 
	SUBTTL	Macro definitions -- PUSH. and POP.
 
;+
;.HL2 PUSH. and POP.
; These macros will save and restore there arguments on a 'stack'.
;-
 
 
	DEFINE PUSH.(VALUE),<
		IFNDEF ..STKP,<..STKP==0>
		IFNDEF VALUE,<VALUE==0>
		$$$PVL==VALUE
		.XCREF	$$$PVL,..STKP
		..STKP==..STKP+1
		PUSH..($$$PVL,\..STKP)
		SUPPRESS ..STKP
		.XCREF	PUSH.,PUSH..
	> ; End of PUSH. definition
 
	DEFINE PUSH..(VALUE,PNTER),<
		.XCREF
		.S$'PNTER==VALUE
		SUPPRESS VALUE
		.CREF
		.XCREF .S$'PNTER
		SUPPRESS .S$'PNTER
	> ; End of PUSH.. definition
 
	DEFINE POP.(VALUE),<
		POP..(VALUE,\..STKP)
		..STKP==..STKP-1
		SUPPRESS ..STKP
		.XCREF	POP.,POP..
	> ; End of POP. definition
 
	DEFINE POP..(VALUE,PNTER),<
		VALUE==.S$'PNTER
		PURGE	.S$'PNTER
	> ; End of POP.. definition
	SUBTTL	Macro definitions -- STORE - Store a value into memory
 
;+
;.HL2 STORE
; This macro will store a value into memory or into a group of memory
;locations.
;-
 
DEFINE	STORE(AC,FIRST,LAST,VALUE),<
	$$$VAL==VALUE
	.XCREF	$$$VAL		;; Dont cref this symbol
	.COND	(<<<$$$VAL>,<SETZM FIRST>>,
		<<$$$VAL+1>,<SETOM FIRST>>,
		<<0>,<MOVX AC,$$$VAL
		     MOVEM AC,FIRST>>>)
	IFNB <LAST>,<
		MOVE	AC,[FIRST,,FIRST+1]
		BLT	AC,LAST
	> ;; End of IFNB <LAST>
	SUPPRESS $$$VAL		;; Make it go away
>; End of STORE definition
	SUBTTL	Macro definitions -- MOVX
 
;+
;.HL2 MOVX
; This macro will generate a MOVE, MOVEI, MOVSI, HRROI, HRLOI
;instruction depending on the value that is being moved.
;-
 
DEFINE	MOVX(AC,VALUE),<
	PUSH.($$$VAL)		;; Allow recursive macro calls
	$$$VAL==VALUE		;; Evaluate the expression
	.XCREF	$$$VAL		;; Dont CREF this
 
	.IFN $$$VAL,ABSOLUTE,<MOVE AC,[VALUE]>
 
	.IF $$$VAL,ABSOLUTE,<
		.COND(<<<$$$VAL_-^D18>,<MOVEI AC,$$$VAL>>,
		   <<$$$VAL_^D18>,<MOVSI AC,($$$VAL)>>,
		   <<<$$$VAL_-^D18>-RH.ALF>,<HRROI AC,$$$VAL>>,
		   <<<$$$VAL_^D18>-LH.ALF>,<HRLOI AC,($$$VAL-RH.ALF)>>,
		   <<0>,<MOVE AC,[$$$VAL]>>>)
	>;; End of .IF $$$VAL,ABSOLUTE
	POP.($$$VAL)		;; Restore the value
	SUPPRES	$$$VAL		;; Suppress it too
>; End of MOVX DEFINITION
	SUBTTL	Macro definitions -- CAX?
 
;+
;.HL2 CAX?
; These macros will generate wither a CAI? or CAM?
;depending upon the value being compared.  (The ? is the suffix for
;the instruction, i.e. GE, G, E, N, LE, L, A, or null).
;-
 
 
DEFINE ..DFCX(SUFFIX),<
	IRP	SUFFIX,<
		DEFINE	CAX'SUFFIX(AC,VALUE),<
			PUSH.($$$VAL)
			$$$VAL==VALUE
			CAX..(AC,SUFFIX)
			POP.($$$VAL)
			SUPPRESS $$$VAL
		>
	> ; End of IRP
> ; End of ..DFCX definition
 
	..DFCX(<,GE,G,E,N,LE,L,A>) ; Define the CAX? macros
	IF2,PURGE ..DFCX	; Get rid of extra macro
 
 
DEFINE	CAX..(AC,SUFFIX),<
	.XCREF	$$$VAL,CAX..	;; Don't cref the symbol or the macro
 
	.IFN $$$VAL,ABSOLUTE,<
		CAM'SUFFIX AC,[$$$VAL]	;; For relocatable, use full word
	> ; End of .IFN $$$VAL,ABSOLUTE
 
	.IF $$$VAL,ABSOLUTE,<
		.COND(<<<<$$$VAL>B53>,<CAI'SUFFIX AC,$$$VAL>>,
		       <<0>,<CAM'SUFFIX AC,[$$$VAL]>>>)
	> ; End of .IF $$$VAL,ABSOLUTE
 
 
> ; End of CAX.. definition
	SUBTTL	Macro definitions -- TX??
 
;+
;.HL2 TX??
; These macros will generate TD??, TL??, or TR?? depending
;upon the value tested.  The ?? are the possible suffixes for the Txxx
;instructions.
;-
 
; Macro to define all the macros
 
DEFINE ..DFTX(X,Y),<
	IRP X,<
		IRP Y,<
			DEFINE TX'X'Y(AC,BITS),<
				PUSH.($$$VAL)
				$$$VAL==BITS
				TX...(AC,X'Y)
				POP.($$$VAL)
				SUPPRESS $$$VAL
			>
		> ;; End IRP Y
	> ;; End of IRP X
> ; End of ..DFTX definition
 
	..DFTX(<N,O,Z,C>,<,E,N,A>) ; Define all the TX??
	PURGE	..DFTX		; PURGE the helper macro
 
 
; Actual macro which does all the work for the TX??'s
 
DEFINE	TX...(AC,SUFFIX),<
	.XCREF	$$$VAL,TX...	;; Don't cref the symbol or the macro
 
	.IFN $$$VAL,ABSOLUTE,<
		TD'SUFFIX AC,[$$$VAL]	;; Use full word for relocatable's
	> ; End of .IFN $$$VAL,ABSOLUTE
 
	.IF $$$VAL,ABSOLUTE,<
		.COND(<<<$$$VAL&LH.ALF>,<TR'SUFFIX AC,$$$VAL>>,
		       <<$$$VAL&RH.ALF>,<TL'SUFFIX AC,($$$VAL)>>,
		       <<<<$$$VAL>B53-RH.ALF>!<..IFIDN(<SUFFIX>,<Z>)&..IFIDN(<SUFFIX>,<O>)&..IFIDN(<SUFFIX>,<C>)>>,<.COND(<
				<<<..IFIDN(<SUFFIX>,<Z>)>>,<ANDI AC,^-$$$VAL>>,
				<<<..IFIDN(<SUFFIX>,<O>)>>,<ORCMI AC,^-$$$VAL>>,
				<<<..IFIDN(<SUFFIX>,<C>)>>,<EQVI AC,^-$$$VAL>>>)>>,
		       <<0>,<TD'SUFFIX AC,[$$$VAL]>>>)
	> ;; End of .IF $$$VAL,ABSOLUTE
 
> ; End of TX... definition
 
 
; Define mnemonic codes for some of the above macros
 
	SYN	TXO,	IORX		; Same macro
	SYN	TXC,	XORX		; . . .
 
DEFINE	ANDX(AC,FLAGS),<
	PUSH.	($$$VAL)		;; Save this value
	$$$VAL==-1-<FLAGS>		;; Define the value
	TX...(AC,Z)			;; Call the correct macro
	POP.	($$$VAL)		;; Restore the old value
>; End of ANDX defintion
	SUBTTL	Macro definitions -- ADDX, SUBX, and etc.
 
;+
;.HL2 Integer arithmetic intstructions
; These macros will generate the proper mode instruction depending upon
;the value being used.
;-
;
 
DEFINE	ADDX(AC,VALUE),<
	PUSH.($$$VAL)
	$$$VAL==VALUE
	ASX...(AC,ADD,SUB)
	POP.($$$VAL)
	SUPPRESS $$$VAL
> ; End of ADDX definition
 
DEFINE	SUBX(AC,VALUE),<
	PUSH.($$$VAL)
	$$$VAL==VALUE
	ASX...(AC,SUB,ADD)
	POP.($$$VAL)
	SUPPRESS $$$VAL
> ; End of SUBX definition
 
; helper macro to define the rest
 
DEFINE	..DFMD(LIST),<
	IRP <LIST>,<
		DEFINE LIST'X(AC,VALUE),<
			PUSH.($$$VAL)
			$$$VAL==VALUE
			AMD...(AC,LIST)
			POP.($$$VAL)
			SUPPRESS $$$VAL
		> ;; End of DEFINE LIST'X
	> ;; End of IRP <LIST>
> ; End of ..DFMD definition
 
	..DFMD(<MUL,IMUL,DIV,IDIV>)
	PURGE	..DFMD		; Get rid of the helper macro
 
 
; The macros which do the work: ASX... and AMD...
 
DEFINE	ASX...(AC,INS,ALT),<
	.XCREF	$$$VAL,ASX...	;; Don't cref the value and the macro
	.IFN $$$VAL,ABSOLUTE,<
		INS	AC,[$$$VAL]	;; Just use the literal if relocatable symbol
	> ; End of .IFN $$$VAL,ABSOLUTE
 
	.IF $$$VAL,ABSOLUTE,<
 
		.COND(<<<$$$VAL-LH.ALF>,<INS AC,[$$$VAL]>>,
		       <<<$$$VAL>B53-RH.ALF>,<ALT'I AC,-<$$$VAL>>>,
		       <<0>,<AMD...(AC,INS)>>>)
	> ;; End of .IF $$$VAL,ABSOLUTE
 
	SUPPRESS $$$VAL		;; Don't leave symbol around later
> ; End of ASX... definition
 
 
DEFINE	AMD...(AC,INS),<
	.XCREF	$$$VAL,AMD...	;; Don't cref the value or the macro
 
	.IFN $$$VAL,ABSOLUTE,<
		INS	AC,[$$$VAL]	;; Use literal for relocatable
	> ;; End of .IFN $$$VAL,ABSOLUTE
 
	.IF $$$VAL,ABSOLUTE,<
		.COND(<<<<$$$VAL>B53>,<INS'I AC,$$$VAL>>,
		       <<0>,<INS AC,[$$$VAL]>>>)
	> ;; End of .IF $$$VAL,ABSOLUTE
 
	SUPPRESS $$$VAL		;; Don't leave this around later
> ; End of AMD... definition
	SUBTTL	Macro definitions -- Floating point (FADRX, etc)
 
;+
;.hl2 FADRX, FSBRX, FMPRX, FDVRX
; The following are the macros for the floating point instructions.  These
;macros are basically the same as the other macro definitions for the ADDX
;and other interger stuff.
;-
 
DEFINE	..DFFP(LIST),<
	IRP LIST,<
		DEFINE	LIST'X(AC,VALUE),<
			PUSH.($$$VAL)
			$$$VAL==VALUE
			..FP(AC,LIST)
			POP.($$$VAL)
			SUPPRESS $$$VAL
		>
	>
>
 
..DFFP(<FADR,FSBR,FMPR,FDVR>)
 
	PURGE	..DFFP
 
 
; Helper macros to generate the floating point instructin
 
DEFINE	..FP(AC,CODE),<
	.XCREF	$$$VAL,..FP	;; Don't CREF this symbol
 
	.IFN $$$VAL,ABSOLUTE,<CODE AC,[$$$VAL]>
 
	.IF $$$VAL,ABSOLUTE,<
		.COND	(<<<$$$VAL_^D18>,<CODE'I AC,($$$VAL)>>,
			<<0>,<CODE AC,[$$$VAL]>>>)
	>; End of .IF $$$VAL,ABSOLUTE
	SUPPRES	$$$VAL		;; Suppress this definition
>; End of ..FP definition
	SUBTTL	Macro definitions -- Structure control -- INTSTR, etc

;+.HL2 Structure definition macros
; This set of macros will define a series of DEFST.'s for a given naming
;system.  Macros are given for defining WORD(including multiple words)
;halfwords, and bytes. Multiple words entries must be accessed with DMOVE's
;(or however many MOVE's are necessary).
;
;Usage:
;
;	INTSTR	(XXX,YY,Z,OFFSET)
;
; This initializes the macros to define offset symbols of the form
;ZYYnam, masks symbols of the form YYZnam, and DEFST. names of the
;form XXXnam. OFFSET is the initial value for the offset symbol.
;
;	WORD(NAM)
;
; This generates a single word entry for NAM.
;
;	WORD(NAM,number)
;
; This generates a multi word entry starting with NAM.
;
;	HALF(NAM)
;
; This generates a halfword entry for NAM.
;
;	BYT(NAM,SIZE)
;
; This generates a byte of width SIZE for NAM.
; SIZE is taken as decimal
;
;	BYT(NAM)
;
; This will define a byte whose width is the rest of the current word.
;
;	BYT(NAM,WID,POS)
;
; This will define a byte ending at bit posistion POS with width WID
; in the next available word with the posistions open.
;
;	BYTM(NAM,MASK)
;
; This will define a byte with mask MASK.
;
;	RHALF	(NAM)
;	LHALF	(NAM)
;
; These macros will generate BYTMs with the masks for the right or left
; half of the word.
;
;	ENDSTR(NAM)
;
; This generates the symbol ZYYNAM which is the length of the block
; If NAM is omitted, ZYYLEN is used.
;-
DEFINE	INTSTR(XXX,YY,Z,OFFS<0>),<
 
	DEFINE	SYNSTR(OLD,NEW),<
		SYN	Z'YY''OLD,Z'YY''NEW	;; Copy the offset
		SYN	YY'Z''OLD,YY'Z''NEW	;; And the mask
		DEFST.(XXX''NEW,Z'YY''NEW,YY'Z''NEW) ;; And define the load/store (no double words)
	> ;; End of DEFINE SYNSTR

	DEFINE	WORD(NAM,NUMB<1>),<
		IFN <..MSK>,<..OFF==..OFF+1> ;; If the mask is partially used, bump to the next word
		DEFSM.(Z'YY''NAM,..OFF)	;; Assign the offset
		DEFSM.(YY'Z''NAM,FW.ORD) ;; define the mask
		IFE <NUMB-1>,DEFST.(XXX''NAM,Z'YY''NAM,YY'Z''NAM,NUMB,SIGNED) ;; Define the LOAD./STORE.  macro
		IFN <NUMB-1>,DEFST.(XXX''NAM,Z'YY''NAM,YY'Z''NAM,NUMB) ;; Define the LOAD./STORE.  macro
 
		..MSK==0		;; Re-initialize the mask
		..OFF==..OFF+NUMB	;; And bump the offset
		SHOW.	Z'YY''NAM	;; Show the offset
		SHOW.	YY'Z''NAM	;; And the mask
	> ;; End of DEFINE WORD
 
 
	DEFINE	HALF(NAM),<
		.COND(<<<..MSK&LH.ALF>,<DEFSM.(YY'Z''NAM,LH.ALF)>>,
		  <<..MSK&RH.ALF>,<DEFSM.(YY'Z''NAM,RH.ALF)>>,
		  <<0>,<..OFF==..OFF+1		;; No - Next word
			..MSK==LH.ALF		;; Flag left half is used
			DEFSM.(YY'Z''NAM,LH.ALF)>>>) ;; And set the mask
 
		DEFSM.(Z'YY''NAM,..OFF)	;; Assign the offset
		DEFST.(XXX''NAM,Z'YY''NAM,YY'Z''NAM) ;; Define the macro
 
		..MSK==..MSK!YY'Z''NAM	;; And set the mask for what we used
		SHOW.	Z'YY''NAM	;; Show the offset
		SHOW.	YY'Z''NAM	;; And the mask
	> ;; End of DEFINE HALF
 
 
	DEFINE BYT(NAM,SIZ,POS),<
		..FLG==0		;; Clear a flag
		IFB <POS>,<IFB <SIZ>,<
			...MSK==RGTMSK(<<^-<<..MSK>>>>)	;; Get the end of the current mask
			IFE ...MSK,<..OFF==..OFF+1	;; If no bits left
				..MSK==0		;; use all of next word
				...MSK==-1		;;  .  .  .
			> ;; End of IFE ...MSK
			BYTM(NAM,<...MSK>) ;; If no size, use the rest
							;; of the word.
			..FLG==-1			;; And set the flag
		>> ;; End of IFB <POS>,IFB <SIZ>
		IFNB <SIZ>,<.SIZ==^D<SIZ>>	;; If we have a size, use it
 
		IFNB <POS>,<		;; Have a position??
			BYTM	(NAM,MASK.(.SIZ,POS)) ;; Yes, make the thing
			..FLG==-1		;; Say we have it
		> ;; End of IFNB <POS>
 
		IFE ..FLG,<IFGE <^D<.SIZ>-^D36>,<	;; Is this a word??
			WORD(NAM,<^D<.SIZ>/^D36>) ;; Yes, define the first second
			IFN <<^D<.SIZ>-<^D<.SIZ>/^D36>*^D36>>,<	;; Is there more??
				BYT(...,<<^D<.SIZ>-<^D<.SIZ>/^D36>*^D36>>) ;; Yes, generate it
				PURGE Z'YY'...,YY'Z'...,XXX'...
			> ;; End of IFN <<^D<.SIZ>-<^D<.SIZ>/^D36>*^D36>>
 
			..FLG==-1	;; Set the flag
		>> ;; End of IFGE <^D<.SIZ>-^D36>
 
		IFE ..FLG,<IFE <^D<.SIZ>-^D18>,<	;; Is it a half word??
			HALF(NAM)	;; Yes, generate it
			..FLG==-1	;; And set the flag
		>> ;; End of IFE <^D<.SIZ>-^D18>
 
		IFE ..FLG,<		;; Have a place yet??
			..BITS==MASK.(^D<.SIZ>,<^D<.SIZ>-1>) ;; No, get a mask for the thing
 
			REPEAT <^D36-^D<.SIZ>+1>,<	;; Find a place in the word
				IFE ..FLG,<	;; Have one yet??
					IFE <..BITS&..MSK>,<	;; No, this one work??
						..MSK==..MSK!..BITS ;; Yes, set the mask
						..FLG==-1	;; And flag we have one
					> ; End of IFE <..BITS&..MSK>
 
				IFE ..FLG,..BITS==..BITS_<-1> ;; Move over one bit
				> ;; End of IFE ..FLG
			> ;; End of REPEAT <^D36-^D<.SIZ>+1>
 
			IFE ..FLG,<	;; Have a mask yet??
				..BITS==MASK.(^D<.SIZ>,<^D<.SIZ>-1>) ;; No, get the mask again
				..OFF==..OFF+1	;; Point to next word
				..MSK==..BITS	;; And set the mask
			> ;; End of IFE ..FLG
 
			DEFSM.(YY'Z''NAM,..BITS) ;; Set the mask
			DEFSM.(Z'YY''NAM,..OFF)	;; And the offset
			DEFST.(XXX''NAM,Z'YY''NAM,YY'Z''NAM) ;; Define the macro
			SHOW.	Z'YY''NAM	;; Show the offset
			SHOW.	YY'Z''NAM	;; And the mask
		> ;; End of IFE ..FLG
	> ;; End of DEFINE BYT
	DEFINE	BYTM(NAM,MASK),<
		IFN MASK&..MSK,<	;; Will this byte fit in the current word??
			..MSK==0	;; No, advance to the next
			..OFF==..OFF+1	;;  .  .  .
		> ;; End of IFN MASK&..MSK
 
		..MSK==..MSK!MASK	;; Flag the part we used
 
		DEFSM.(Z'YY''NAM,..OFF)	;; Define the offset
		DEFSM.(YY'Z''NAM,MASK)	;; Define the mask
		DEFST.(XXX''NAM,Z'YY''NAM,YY'Z''NAM) ;; Define the macro
		SHOW.	Z'YY''NAM	;; Show the offset
		SHOW.	YY'Z''NAM	;; And the mask
	> ;; End of DEFINE BYTM
 
 
	DEFINE ENDSTR(NAM<LEN>),<
 
		IFN ..MSK,<..OFF==..OFF+1>	;; Bump the offset if
						;; nothing in this word
		DEFSM.(Z'YY''NAM,..OFF)	;; Define the length
 
		SHOW.	Z'YY''NAM	;; Show the length
		IF2,<
			IFDEF ...MSK,<SUPPRESS ...MSK>
			IFDEF ..BITS,<SUPPRESS ..BITS>
			IFDEF .SIZ,<SUPPRESS .SIZ>
			IFDEF ..MSK,<SUPPRESS ..MSK>
			IFDEF ..OFF,<SUPPRESS ..OFF>
			IFDEF ..FLG,<SUPPRESS ..FLG>
		>; End of IF2
		IF1,<
			IFDEF ...MSK,<.XCREF ...MSK>
			IFDEF ..BITS,<.XCREF ..BITS>
			IFDEF .SIZ,<.XCREF .SIZ>
			IFDEF ..MSK,<.XCREF ..MSK>
			IFDEF ..FLG,<.XCREF ..FLG>
			IFDEF ..OFF,<.XCREF ..OFF>
		>; End of IF1
	> ;; End of DEFINE ENDSTR
 
	..MSK==0	;; Initialize the mask
	..OFF==OFFS	;; And the offset
 
 
 
> ;; End of DEFINE INTSTR
; Helper macros:
;
 
DEFINE	RGTMSK(MASK)<<IFE <<FILIN.(<MASK>)&<^-MASK>>>,<MASK>>!<IFN <<FILIN.(<MASK>)&<^-MASK>>><<FILIN.(<<<RGHBT.(<<FILIN.(<MASK>)&<^-MASK>>>)>_-1>>!<RGHBT.(MASK)>)>>>>
 
DEFINE	RHALF(NAME)<	BYTM	(NAME,RH.ALF)>
 
DEFINE	LHALF(NAME)<	BYTM	(NAME,LH.ALF)>

DEFINE DEFSM.(SYMBOL,VALUE),<
	IF1,<IFDEF SYMBOL,<
		.IF SYMBOL,LOCAL,<
			IFN <SYMBOL-VALUE>,<
			PRINTX ? SYMBOL is multiply defined>>
		.IFN SYMBOL,LOCAL,<PRINTX ? SYMBOL is multiply defined>>
	     IFNDEF SYMBOL,<SYMBOL==VALUE>>
	IF2,<SYMBOL==VALUE>
>
	SUBTTL	Macro definitions -- Structure control -- DEFST.
 
;+
;.hl1 Structure macros
; These macros are used for manipulating fields in structures.
;.lm+5
;.hl2 DEFST.
; This macro is used to define a structure.
;.lm-5
;-
 
DEFINE	DEFST.(NAME,LOC,MASK,NUMWDS,SIGNFL),<
	..NUM==1
	..SGN==0
	.XCREF ..NUM,..SGN	;; Don't cref these
	IFNB <NUMWDS>,<..NUM==NUMWDS> ;; Copy the arg if given
	IFNB <SIGNFL>,<		;; Copy the signed/unsigned flag
		.COND(<<<..IFIDN(SINGFL,SIGNED)&..IFE(MASK+1)>,<..SGN==D%.SGN>>,
			<<..IFIDN(SINGFL,UNSIGNED)>,<>>,
			<<0>,<PRINTX ? SIGNFL should be either SIGNED or UNSIGNED>>>)
	> ;; End of IFNB SIGNFL
	DEFS..(NAME,<LOC>,<MASK>,\..NUM,\..SGN)
>; End of DEFST. definition

DEFINE	DEFS..(NAME,LOC,MASK,NUMWDS,FLAGS),<
	DEFINE	NAME(MACRO,AC,Y,LIST),<
		MACRO	(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,<LIST>)
	> ;; End of NAME definition
> ; End of DEFS.. definition
 

; Flags for DEFST. macros

	D%.SGN==	1B0		; Signed field
SUBTTL	Macro definitions -- Structure control -- $SET, $BUILD, and $EOB

;+
;.HL1 $BUILD, $SET, $EOB
;These macros are used to building a block.  That was defined with a DEFST.
;or INTSTR macros.
;.literal
;
; Usage:
;	$BUILD	XXX,Length
;	  $SET	YYY,Value
;	  $SET	ZZZ,Value
;	$EOB
;
; XXXYYY and XXXZZZ are the names of DEFST.'s that have been defined.
;.end literal
;-

DEFINE	$BUILD(PREFIX,SIZE),<
    IFDEF ..BSIZ,<PRINTX ?Missing $EOB after a $BUILD>
    ..BSIZ==0			;; Start the counter
    ..BLOC==.			;; Start of the block
    REPEAT SIZE,<
	BLD0.(\..BSIZ,0)	;; Zero out the block
	..BSIZ==..BSIZ+1	;; And step to the next
    >; End of REPEAT SIZE

DEFINE	$SET(STR,VALUE),<
	PREFIX''STR (..SET,,,<VALUE>)
>

DEFINE	$SETFL(STR,VALUE),<
	PREFIX''STR (..STF,,,<VALUE>)
>

DEFINE	$EOB,<
  IFN <.-..BLOC>,<PRINTX ?Address change between $BUILD(PREFIX,SIZE) and $EOB>
  LSTOF.			;; Turn the listing off
  ..T==0			;; Initialize the counter
  REPEAT ..BSIZ,<
     BLD0.(\..T,1)		;; Store each word
     ..T==..T+1			;; Increment the word
  >
  PURGE  ..T,..BSIZ,..BLOC,$SET,$EOB
  LSTON.
>; End of $EOB defintion
>; End of $BUILD macro definition


DEFINE BLD0.(N,WHAT),<
    IFE WHAT,<..T'N==0>		;; Initialize
    IFN WHAT,<EXP ..T'N		;; Generate the value
	    PURGE ..T'N>	;; Delete the symbol
>; End of BLD0. macro definition


DEFINE ..SET(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,VALUE)<
    ...SET(\LOC,MASK,NUMWDS,NAME,<VALUE>)
>
DEFINE ...SET(LOC,MASK,NUMWDS,NAME,VALUE),<
  IFN <<..T'LOC>&MASK>,<PRINTX ?Initial value of NAME not zero in $SET>
  IFN NUMWDS-1,<PRINTX ?Only single word values allowed in $SET>
  ..T'LOC==..T'LOC!<INSVL.(<<VALUE>>,MASK)>
>; End of ...SET macro definition


DEFINE ..STF(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,VALUE)<
   ...STF(\LOC,MASK,NUMWDS,NAME,<VALUE>)
>

DEFINE ...STF(LOC,MASK,NUMWDS,NAME,VALUE),<
    IFN NUMWDS-1,<PRINTX ?Only single word values allowed in $SET>
    ..T'LOC==..T'LOC!<VALUE>
>; End of ...STF macro definition
	SUBTTL	Macro definitions -- Structure control -- LOAD
 
;+
;.lm+5
;.hl2 LOAD
; This macro is similar to the LOAD. macro, except that the macro uses
;just a mask, register and address.
;.lm-5
;-
 
DEFINE	LOAD(AC,ADDRESS,MASK),<..LOAD	(AC,,ADDRESS,MASK,1,MASK,0,)>
	SUBTTL	Macro definitions -- Structure control -- LOAD.
 
 
;+
;.LM+5.HL2 LOAD.
; This macro is used to fetch a field from a structure.  This macro will
;always generate at least one word.
;.lm-5
;-
 
DEFINE	LOAD.(AC,NAME,Y),<NAME	(..LOAD,AC,Y,)>
 
DEFINE	..LOAD(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..LOAD
    IFE <FLAGS>&<D%.SGN>,<
	.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<DMOVE AC,LOC'Y>>,
				    <<NUMWDS-1>,<MOVE AC,LOC'Y>>,
				    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
		<<MASK-RH.ALF>,<HRRZ AC,LOC'Y>>,
		<<MASK-LH.ALF>,<HLRZ AC,LOC'Y>>,
		<<0>,<LDB AC,[POINTR(LOC'Y,MASK)]>>>)
    > ;; End of IFE FLAGS&D%.SGN
    IFN <FLAGS>&<D%.SGN>,<
	..LODE(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,<LIST>)
    > ;; End of IFN FLAGS&D%.SGN
>; End of ..LOAD definition
	SUBTTL	Macro definitions -- Structure control -- LOADS.
 
 
;+
;.LM+5.HL2 LOADS.
; This macro is used to fetch a field from a structure.  This macro will
;put the value fetched into the left half of the ac.  Note that LOADS.
;on a byte will put the value in the left half at the expense of the
;current value in the right half of the ac.  This macro will
;always generate at least one word.
;.lm-5
;-
 
DEFINE	LOADS.(AC,NAME,Y),<NAME	(..LODS,AC,Y,)>
 
DEFINE	..LODS(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..LODS
	.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<MOVE AC+1,LOC'Y
						  MOVE AC,LOC+1'Y>>,
				    <<NUMWDS-1>,<MOVS AC,LOC'Y>>,
				    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
		<<MASK-RH.ALF>,<HRLZ AC,LOC'Y>>,
		<<MASK-LH.ALF>,<HLLZ AC,LOC'Y>>,
		<<0>,<.COND(<<<..IFL <WID(MASK)-^D18>>,<LDB AC,[POINTR(LOC'Y,MASK)]
						     MOVS AC,AC>>,
			<<0>,<PRINTX ? How do you fit MASK in 18 bits for structure NAME?>>>)>>>)
>; End of ..LODS definition
	SUBTTL	Macro definitions -- Structure control -- LOADE.
 
 
;+
;.LM+5.HL2 LOADE.
; This macro is used to fetch a field from a structure.  This macro will
;always generate at least one word.
;.lm-5
;-
 
DEFINE	LOADE.(AC,NAME,Y),<NAME	(..LODE,AC,Y,)>
 
DEFINE	..LODE(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..LODE
	.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<DMOVE AC,LOC'Y>>,
				    <<NUMWDS-1>,<MOVE AC,LOC'Y>>,
				    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
		<<MASK-RH.ALF>,<HRRE AC,LOC'Y>>,
		<<MASK-LH.ALF>,<HLRE AC,LOC'Y>>,
		<<0>,<LDB AC,[POINTR(LOC'Y,MASK)]
		      TXNE AC,<<LFTBT.(MASK)>_-<ALIGN.(MASK)>>
		       TXO AC,<^-<<MASK>_-<ALIGN.(MASK)>>>>>>)
>; End of ..LODE definition
	SUBTTL	Macro definitions -- Structure control -- STOR
 
;+
;.lm+5
;.HL2 STOR
; What this macro is to STOR. the LOAD macro is to LOAD.
;.lm-5
;-
 
DEFINE	STOR(AC,ADDRESS,MASK),<..STOR(AC,,ADDRESS,MASK,1,MASK,,)>
	SUBTTL	Macro definitions -- Structure control -- STOR.
 
 
;+
;.LM+5.HL2 STOR.
; This macro is used to store a field from a structure.  This macro will
;always generate at least one word.
;.lm-5
;-
 
DEFINE	STOR.(AC,NAME,Y),<NAME	(..STOR,AC,Y,)>
 
DEFINE	..STOR(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..STOR
	.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<DMOVEM AC,LOC'Y>>,
				    <<NUMWDS-1>,<MOVEM AC,LOC'Y>>,
				    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
		<<MASK-RH.ALF>,<HRRM AC,LOC'Y>>,
		<<MASK-LH.ALF>,<HRLM AC,LOC'Y>>,
		<<0>,<DPB AC,[POINTR(LOC'Y,MASK)]>>>)
>; End of ..STOR definition
	SUBTTL	Macro definitions -- Structure control -- STORS.
 
 
;+
;.LM+5.HL2 STORS.
; This macro is used to store a field from a structure (swapped).
; This macro will always generate at least one word.
;.lm-5
;-
 
DEFINE	STORS.(AC,NAME,Y),<NAME	(..STRS,AC,Y,)>
 
DEFINE	..STRS(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..STRS
	.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<MOVEM AC,LOC+1'Y
						  MOVEM AC+1,LOC'Y>>,
				    <<NUMWDS-1>,<MOVSM AC,LOC'Y>>,
				    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
		<<MASK-RH.ALF>,<HLRM AC,LOC'Y>>,
		<<MASK-LH.ALF>,<HLLM AC,LOC'Y>>,
		<<0>,<.COND(<<<..IFL <WID(MASK)-^D18>>,<MOVS AC,AC
		      DPB AC,[POINTR(LOC'Y,MASK)]>>,
			<<0>,<PRINTX ? How do you fit MASK in 18 bits for structure NAME?>>>)>>>)
>; End of ..STRS definition
	SUBTTL	Macro definitions -- Structure control -- STORI.
 
;+
;.lm+5
;.HL2 STORI.
; This macro will store the value into the field of the structure. It
;will generate the least code to do so.
;.lm-5
;-
 
DEFINE STORI.(VALUE,AC,NAME,Y),<
	PUSH.($$$VAL)
	$$$VAL==VALUE		;; Get the value
	.XCREF	$$$VAL		;; And don't cref it
	NAME(..STRI,AC,Y,$$$VAL)
	POP.($$$VAL)
	SUPPRESS $$$VAL
> ; End of STORI. definition
 
DEFINE ..STRI(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,$$$VAL),<
	.XCREF	..STRI
    .IF $$$VAL,ABSOLUTE,<
	.COND(<<<$$$VAL&<<MASK>_-<ALIGN.(MASK)>>>,<..ZERO(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,)>>,
	       <<<FILIN.(<<$$$VAL&<LFTBT.(<<MASK>_-<ALIGN.(MASK)>>)>>_<^L<MASK>>!<$$$VAL&<LFTBT.(<<MASK>_-<ALIGN.(MASK)>>)>>>)!$$$VAL>+1>,<..ONES(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,)>>,
	       <<0>,<
			$$$LOC==LOC'Y	;; Copy the location
			.XCREF	$$$LOC	;; And don't cref it
			.COND(<<<..TSAC($$$LOC)>,<IFB <AC>,<PRINTX ? Cannot store value into NAME without a register>
					IFNB <AC>,<
					    .COND(<<<NUMWDS-2>,<SETZM LOC'Y
						MOVX AC,$$$VAL
						..STOR(AC,Y,LOC+1,MASK,NUMWDS-1,NAME,FLAGS,)>>,
						<<0>,<MOVX AC,$$$VAL
						..STOR(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,)>>>)
					    > ;; End of IFNB <AC>
					>>,
				<<0>,<.COND(<<<MASK+1>,<.COND(<<<NUMWDS-2>,<SETZ $$$LOC,
									  MOVX $$$LOC+1,$$$VAL>>,
								<<0>,<MOVX $$$LOC,$$$VAL>>>)>>,
					<<MASK-LH.ALF>,<HRLI $$$LOC,$$$VAL>>,
					<<MASK-RH.ALF>,<HRRI $$$LOC,$$$VAL>>,
					<<0>,<TXZ $$$LOC,MASK
					      TXO $$$LOC,<INSVL.($$$VAL,MASK)>>>>)
		>>>)
	>>>);; End of first .COND
    > ;; End of .IF $$$VAL,ABSOLUTE
    .IFN $$$VAL,ABSOLUTE,<	;; For relocatable and external symbols
	IFB <AC>,<PRINTX ? Need a register to STORI. non-absolute value into NAME>
	IFNB <AC>,<
		.COND(<<<NUMWDS-2>,<SETZM LOC'Y
			IFG WID(MASK)-^D18,<MOVE AC,[EXP $$$VAL]>
			IFLE WID(MASK)-^D18,<MOVEI AC,$$$VAL>
			..STOR(AC,Y,LOC+1,MASK,NUMWDS-1,NAME,FLAGS,)>>,
			<<0>,<
			IFG WID(MASK)-^D18,<MOVE AC,[EXP $$$VAL]>
			IFLE WID(MASK)-^D18,<MOVEI AC,$$$VAL>
			..STOR(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,)>>>)
		> ;; End of IFNB <AC>
    > ;; End of .IFN $$$VAL,ABSOLUTE
> ; End of ..STRI definition
 
	SUBTTL	Macro definitions -- Structure control -- ZERO.
 
 
;+
;.LM+5.HL2 ZERO.
; This macro is used to zero a field in a structure.  This macro will
;always generate at least one word.
;.lm-5
;-
 
DEFINE	ZERO.(AC,NAME,Y),<NAME	(..ZERO,AC,Y,)>
 
DEFINE	..ZERO(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..ZERO
	IFB <AC>,<
		$$$LOC==LOC'Y
		.COND(<<<..TSAC($$$LOC)>,<
			.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<SETZM LOC'Y
								SETZM LOC+1'Y>>,
						    <<NUMWDS-1>,<SETZM LOC'Y>>,
						    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
				<<MASK-RH.ALF>,<HLLZS LOC'Y>>,
				<<MASK-LH.ALF>,<HRRZS LOC'Y>>,
				<<0>,<PRINTX ? Can not zero byte NAME>>>)>>,
			<<0>,<.COND(<<<MASK+1>,<.COND(<<<NUMWDS-2>,<SETZB LOC+1'Y,LOC'Y>>,
						       <<NUMWDS-1>,<SETZ  LOC'Y,>>,
							<<0>,<PRINTX ? Too many words for structure NAME>>>)>>,
				     <<0>,<TXZ LOC'Y,MASK>>>)>>>)
 
	>; End of IFB <AC>
 
	IFNB <AC>,<
		.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<SETZB AC,LOC'Y
							SETZB AC+1,LOC+1'Y>>,
					    <<NUMWDS-1>,<SETZB AC,LOC'Y>>,
					    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
		<<MASK-RH.ALF>,<HLLZS AC,LOC'Y>>,
		<<MASK-LH.ALF>,<HRRZS AC,LOC'Y>>,
		<<0>,<MOVX AC,MASK
		      ANDCAB AC,LOC'Y>>>)
	>; End of IFNB <AC>
>; End of ..ZERO definition
	SUBTTL	Macro definitions -- Structure control -- ONES.
 
 
;+
;.LM+5.HL2 ONES.
; This macro is used to set a field in a structure to all ones. This macro will
;always generate at least one word.
;.lm-5
;-
 
DEFINE	ONES.(AC,NAME,Y),<NAME	(..ONES,AC,Y,)>
 
DEFINE	..ONES(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..ONES
	IFB <AC>,<
		$$$LOC==LOC'Y
		.COND(<<<..TSAC($$$LOC)>,<
			.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<SETOM LOC'Y
								SETOM LOC+1'Y>>,
						    <<NUMWDS-1>,<SETOM LOC'Y>>,
						    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
				<<MASK-RH.ALF>,<HLLOS LOC'Y>>,
				<<MASK-LH.ALF>,<HRROS LOC'Y>>,
				<<0>,<PRINTX ? Can not set byte NAME to ones>>>)>>,
			<<0>,<.COND(<<<MASK+1>,<.COND(<<<NUMWDS-2>,<SETOB LOC+1'Y,LOC'Y>>,
						       <<NUMWDS-1>,<SETO  LOC'Y,>>,
							<<0>,<PRINTX ? Too many words for structure NAME>>>)>>,
				     <<0>,<TXO LOC'Y,MASK>>>)>>>)
 
	>; End of IFB <AC>
 
	IFNB <AC>,<
		.COND	(<<<MASK+1>,<.COND (<<<NUMWDS-2>,<SETOB AC,LOC'Y
							SETOB AC+1,LOC+1'Y>>,
					    <<NUMWDS-1>,<SETOB AC,LOC'Y>>,
					    <<0>,<PRINTX ?Too many words for structure NAME>>>)>>,
		<<MASK-RH.ALF>,<HLLOS AC,LOC'Y>>,
		<<MASK-LH.ALF>,<HRROS AC,LOC'Y>>,
		<<0>,<MOVX AC,MASK
		      IORB AC,LOC'Y>>>)
	>; End of IFNB <AC>
>; End of ..ONES definition
	SUBTTL	Macro definitions -- Structure control -- INCR.
 
;+
;.lm+5
;.HL2 INCR.
; This macro will increment the value in the field. It may generate
;more than one instruction.
;.lm-5
;-
 
DEFINE INCR.(AC,NAME,Y),<NAME(..INCR,AC,Y)>
 
DEFINE ..INCR(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..INCR
	$$$LOC==LOC'Y
	.XCREF $$$LOC,..INCR
 
	.COND(<<<..TSAC($$$LOC)>,<.COND(<<<..IFB <AC>>,<
					.COND(<<<NUMWDS-2>,<PRINTX ? Cannot increment double word NAME without a register>>,
					     <<0>,<.COND(<<<RGHBT.(MASK)-1>,<AOS LOC'Y>>,
							<<0>,<PRINTX ? Cannot increment NAME without a register>>>) >>>) >>,
					<<0>,<.COND(<<<NUMWDS-2>,<SETZ AC,
								MOVEI AC+1,1
								DADD AC,LOC'Y
								DMOVEM AC,LOC'Y>>,
							<<0>,<.COND(<<<RGHBT.(MASK)-1>,<AOS AC,LOC'Y>>,
						<<0>,<MOVX AC,<RGHBT.(MASK)>
						      ADDB AC,LOC'Y >>>) >>>) >>>) >>,
		<<0>,<.COND(<<<NUMWDS-2>,<DADD LOC'Y,[EXP 0,1]
					IFNB <AC>,<DMOVE AC,LOC'Y>>>,
			<<0>,<.COND(<<<<RGHBT.(MASK)-1>!<..IFNB(AC)>>,<AOS AC,LOC'Y>>,
				<<0>,<ADDX LOC'Y,<RGHBT.(MASK)>
					IFNB <AC>,<MOVE AC,LOC'Y> >>>) >>>) >>>)
	SUPPRESS $$$LOC
> ; End of ..INCR definition
	SUBTTL	Macro definitions -- Structure control -- DECR.
 
;+
;.lm+5
;.HL2 DECR.
; This macro will decrement the value in the field. It may generate
;more than one instruction.
;.lm-5
;-
 
DEFINE DECR.(AC,NAME,Y),<NAME(..DECR,AC,Y)>
 
DEFINE ..DECR(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..DECR
	$$$LOC==LOC'Y
	.XCREF $$$LOC,..DECR
 
	.COND(<<<..TSAC($$$LOC)>,<.COND(<<<..IFB <AC>>,<
					.COND(<<<NUMWDS-2>,<PRINTX ? Cannot decrement double word NAME without a register>>,
					     <<0>,<.COND(<<<RGHBT.(MASK)-1>,<SOS LOC'Y>>,
							<<0>,<PRINTX ? Cannot decrement NAME without a register>>>) >>>) >>,
					<<0>,<.COND(<<<NUMWDS-2>,<DMOVE AC,LOC'Y
								DSUB AC,[EXP 0,1]
								DMOVEM AC,LOC'Y>>,
							<<0>,<.COND(<<<RGHBT.(MASK)-1>,<SOS AC,LOC'Y>>,
						<<0>,<MOVX AC,-<RGHBT.(MASK)>
						      ADDB AC,LOC'Y >>>) >>>) >>>) >>,
		<<0>,<.COND(<<<NUMWDS-2>,<DSUB LOC'Y,[EXP 0,1]
					IFNB <AC>,<DMOVE AC,LOC'Y>>>,
			<<0>,<.COND(<<<<RGHBT.(MASK)-1>!<..IFNB(AC)>>,<SOS AC,LOC'Y>>,
				<<0>,<SUBX LOC'Y,<RGHBT.(MASK)>
					IFNB <AC>,<MOVE AC,LOC'Y> >>>) >>>) >>>)
	SUPPRESS $$$LOC
> ; End of ..DECR definition
	SUBTTL	Macro definitions -- Structure control -- CFMxx.
 
;+
;.lm+5
;.hl2 CFMxx.
; These macro will generate a code to skip if, when compared to the value
;in the address given, the value in the field is in the true releation.
;(I.e. the value in the field is less than the value given when the xx in
;the macro name is L.)
;.lm-5
;-
 
 
; Helper macro
 
DEFINE ..DFCF(LIST),<IRP LIST,<...DFC LIST>>
DEFINE ...DFC(LIST),<....DF LIST>
DEFINE ....DF(TYP1,TYP2,TYP3,TYP4),<
	DEFINE CFM'TYP1'.(AC,NAME,Y,VALUE),<NAME(..CFM,AC,Y,<VALUE,TYP1,TYP2,TYP3,TYP4>)>
>
 
..DFCF(<<E,E,,>,<N,N,,>,<GE,LE,LE,GE>,<LE,GE,GE,LE>,<G,L,LE,GE>,<L,G,GE,LE>>)
	PURGE	..DFCF,...DFC,....DF

DEFINE	..CFM(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF	..CFM
   DEFINE ...CFM(VALUE,PST1,PST2,PST3,PST4),<
	.XCREF	...CFM
	$$$LOC==LOC'Y
	$$$VAL==VALUE
	.XCREF	$$$LOC,$$$VAL

	.COND(<<<<MASK+1>!<^-<..TSAC($$$LOC)!..TSAC($$$VAL)>>>,<
	    .COND(<<<^-..TSAC($$$VAL)>,<
		.COND(<<<NUMWDS-1>,<CAM'PST2 $$$VAL,LOC'Y>>,
		     <<NUMWDS-2>,<
			.COND(<<<..IFIDN(PST1,E)&..IFIDN(PST1,N)>,<
			    CAMN  $$$VAL,LOC'Y
			     CAME $$$VAL+1,1+LOC'Y
			IFIDN <PST1>,<E>,<SKIPA>>>,
			<<0>,<CAMN $$$VAL,LOC'Y
			     CAM'PST2 $$$VAL+1,1+LOC'Y
			     CAM'PST4 $$$VAL,LOC'Y>>>)>>,
		 <<0>,<PRINTX ?Too many words for NAME>>>)>>,
	    <<0>,<.COND(<<<NUMWDS-1>,<CAM'PST1 $$$LOC,VALUE>>,
		<<NUMWDS-2>,<
		    .COND(<<<..IFIDN(PST1,E)&..IFIDN(PST1,N)>,<
			CAMN	$$$LOC,VALUE
			CAME	$$$LOC+1,1+VALUE
			IFIDN <PST1>,<E>,<SKIPA>>>,
		    <<0>,<CAMN	$$$LOC,VALUE
			CAM'PST1 $$$LOC+1,1+VALUE
			CAM'PST3 $$$LOC,VALUE>>>)>>,
		<<0>,<PRINTX ? Too many words for NAME>>>)>>>)>>,
	<<..IFB(AC)>,<PRINTX ? Need a register to compare NAME>>,
	<<0>,<..LOAD AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,
	    .COND(<<<NUMWDS-1>,<CAM'PST1 AC,VALUE>>,
		<<0>,<.COND(<<<..IFIDN(PST1,E)&..IFIDN(PST1,N)>,<
			CAMN	AC,VALUE
			CAME	AC+1,1+VALUE
			IFIDN <PST1>,<E>,<SKIPA>>>,
		    <<0>,<CAMN	AC,VALUE
			CAM'PST1 AC+1,1+VALUE
			CAM'PST3 AC,VALUE>>>)>>>)>>>)
	SUPPRES	$$$LOC,$$$VAL
    >;; End of ...CFM macro definition
   ...CFM LIST
>; End of ..CFM macro definition
	SUBTTL	Macro definitions -- Structure control -- CFXxx.

;+
;.hl2 CFXxx.
; These macros will generate the code to compare the value to the value in
;the field and skip if the condition is met.
;-


; Helper macros to define the real macros

DEFINE ..DFCF(LIST),<IRP LIST,<...DFC LIST>>
DEFINE ...DFC(LIST),<....DF LIST>
DEFINE ....DF(TYP1,TYP2),<
	DEFINE CFX'TYP1'.(AC,NAME,Y,VALUE),<NAME(..CFX,AC,Y,<VALUE,TYP1,TYP2>)>
	DEFINE CFX'TYP2'.(AC,NAME,Y,VALUE),<NAME(..CFX,AC,Y,<VALUE,TYP2,TYP1>)>
>

	..DFCF(<<E,N>,<,A>,<LE,G>,<L,GE>>)
	PURGE	..DFCF,...DFC,....DF


DEFINE	..CFX(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,LIST),<
	.XCREF ..CFX
	DEFINE	...CFX(VALUE,POST,ALTPST,%1),<
	.XCREF	...CFX
	$$$LOC==LOC'Y
	$$$VAL==VALUE
	.XCREF $$$LOC,$$$VAL

	.COND(<<<..IFE($$$VAL)>,<.COND(<<<..IFE(MASK+1)>,<
					.COND(<<<..IFE(NUMWDS-1)>,<SKIP'POST LOC'Y>>,
						<<..IFE(NUMWDS-2)>,<
						.COND(<<<<..IFIDN(POST,N)>&<..IFIDN(POST,E)>>,<
							SKIP'ALTPST LOC'Y
							SKIP''POST   1+LOC'Y>>,
							<<..IFIDN(POST,L)&..IFIDN(POST,GE)>,
							<SKIP'POST LOC'Y>>,
							<<..IFIDN(POST,LE)>,<
							SKIPGE LOC'Y
							 JRST	%1+1
							SKIPN  1+LOC'Y
							 SKIPE LOC'Y>>,
							<<0>,<
							SKIPLE LOC'Y
							 JRST  %1+1
							SKIPN  1+LOC'Y
							 SKIPE LOC'Y>>>)>>,
						<<0>,<PRINTX ? Two many words to compare>>>)>>,
				<<..IFE(MASK-1B0)>,<.COND(<<<..IFIDN(POST,N)>,<
							SKIPL	LOC'Y>>,
							<<0>,<SKIPGE LOC'Y>>>)>>,
				<<..IFE(FLAGS&D%.SGN)>,<.COND(<<<..IFIDN(POST,L)>,
								<PRINTX  Unsigned field is never less than zero>>,
							<<..IFIDN(POST,GE)>,
							<PRINTX ? Unsigned field is always greater than or equal to zero>>,
							<<..IFB(AC)!<^-..TSAC($$$LOC)>>,<PRINTX ?Need a register to compare VALUE to NAME>>,
							<<..IFIDN(POST,E)&..IFIDN(POST,LE)>,<
							.COND(<<<<^-..TSAC($$$LOC)>>,<
								TXNE $$$LOC,MASK>>,
							<<0>,<
								MOVX AC,MASK
								TDNE AC,LOC'Y>>>)>>,
							<<0>,<.COND(<<<<^-..TSAC($$$LOC)>>,<
								TXNN LOC'Y,MASK>>,
								<<0>,<
								MOVX AC,MASK
								TDNN AC,LOC'Y>>>)>>>)>>,
				<<..IFE(MASK&1B0)!<..IFIDN(POST,L)&..IFIDN(POST,G)&
						..IFIDN(POST,GE)>>,<SKIP'POST LOC'Y>>,
				<<..IFB(AC)!<^-..TSAC($$$LOC)>>,<PRINTX ? Need a register to compare VALUE to NAME>>,
				<<..IFIDN(POST,E)>,<.COND(<<<<^-..TSAC($$$LOC)>>,<
							TXNE LOC'Y,MASK>>,
							<<0>,<MOVX AC,MASK
								TDNE AC,LOC'Y>>>)>>,
				<<..IFIDN(POST,N)>,<.COND(<<<<^-..TSAC($$$LOC)>>,<TXNN LOC'Y,MASK>>,
							<<0>,<MOVX AC,MASK
								TDNN AC,LOC'Y>>>)>>,
				<<..IFIDN(POST,L)>,<.COND(<<<^-..TSAC($$$LOC)>,
							<TXNN LOC'Y,<LFTBT.(MASK)>>>,
							<<0>,<MOVX AC,<LFTBT.(MASK)>
								TDNN AC,LOC'Y>>>)>>,
				<<..IFIDN(POST,GE)>,<.COND(<<<<^-..TSAC($$$LOC)>>,<
							TXNE AC,<LFTBT.(MASK)>>>,
							<<0>,<MOVX AC,<LFTBT.(MASK)>
								TDNE AC,LOC'Y>>>)>>,
				<<..IFIDN(POST,LE)>,<.COND(<<<^-..TSAC($$$LOC)>,<TXNE LOC'Y,<LFTBT.(MASK)>
								TXNN LOC'Y,MASK
								 TRNA>>,
							<<0>,<MOVX AC,<LFTBT.(MASK)>
								TDNE AC,LOC'Y
								JRST %1+1
								MOVX AC,MASK
								TDNE AC,LOC'Y>>>)>>,
				<<0>,<.COND(<<<^-..TSAC($$$LOC)>,<TXNE LOC'Y,MASK
						TXNE LOC'Y,<LFTBT.(MASK)>>>,
					<<0>,<MOVX AC,MASK
					      TDNN AC,LOC'Y
					       JRST %1
					      MOVX AC,<LFTBT.(MASK)>
					      TDNE AC,LOC'Y>>>)>>>)>>,
	<<..IFGE($$$VAL)!..IFG(<$$$VAL-<$$$VAL&<<MASK>_-<ALIGN.(MASK)>>>>)>,<PRINTX ? VALUE is outside of valid range for NAME>>,
	<<..IFE(FLAGS&D%.SGN)!..IFL($$$VAL)>,<PRINTX ? Negative values (VALUE) not permitted in unsigned field>>,
	<<..IFL($$$VAL)!..IFG(<-$$$VAL-<-$$$VAL&<<MASK>_<ALIGN.(MASK)>>>>)>,<PRINTX ? VALUE is otside of valid range for NAME>>,
	<<..IFN(<^D36-WID(MASK)>)!..IFG($$$VAL)!..IFIDN(POST,G)!..IFG(<$$$VAL-<MASK.(<WID(MASK)>,35)>>)>,<PRINTX ? NAME is never greater than VALUE>>,
	<<..IFN(<^D36-WID(MASK)>)!..IFL($$$VAL)!..IFIDN(POST,L)!..IFE(<-$$$VAL-<-$$$VAL&<<MASK>_<ALIGN.(MASK)>>>>)>,<PRINTX ? NAME is never less than VALUE>>,
	<<..IFE(MASK+1)!<^-..TSAC($$$LOC)>>,<.COND(<<<..IFE(NUMWDS-1)>,<
								CAX'POST LOC'Y,$$$VAL>>,
						<<..IFE(NUMWDS-2)>,<
						.COND(<<<..IFIDN(POST,E)>,<
							CAXN LOC'Y,$$$VAL
							 CAIE 1+LOC'Y,0>>,
						<<..IFIDN(POST,N)>,<
							CAXN	LOC'Y,$$$VAL
							 CAIE	1+LOC'Y,0
							  TRNA>>,
						<<..IFIDN(POST,G)&..IFIDN(POST,LE)>,<
							CAX'POST LOC'Y,$$$VAL
							 CAI'ALTPST 1+LOC'Y,0
							  CAXN LOC'Y,$$$VAL>>,
						<<..IFIDN(POST,GE)>,<
							CAXGE	LOC'Y,$$$VAL
							 CAILE	1+LOC'Y,0
							  CAXN	LOC'Y,$$$VAL>>,
						<<0>,<CAXLE	LOC'Y,$$$VAL
							CAIGE	1+LOC'Y,0
							 CAXN	LOC'Y,$$$VAL>>>)>>,
					<<0>,<PRINTX ? Two many words to compare for NAME>>>)>>,
			<<..IFE(WID(MASK)-1)>,<.COND(<<<^-..TSAC($$$LOC)>,<
					.COND(<<<..IFIDN(POST,N)&..IFIDN(POST,L)>,<
						TXNE LOC'Y,MASK>>,
					<<..IFIDN(POST,E)&..IFIDN(POST,GE)>,<
						TXNN LOC'Y,MASK>>>)>>,
				<<..IFE(MASK-1B0)>,<.COND(<<<..IFIDN(POST,N)&..IFIDN(POST,L)>,<
					SKIPGE	LOC'Y>>,
					<<..IFIDN(POST,E)&..IFIDN(POST,GE)>,<
					SKIPL LOC'Y>>>)>>,
				<<0>,<.COND(<<<..IFB(AC)>,<PRINTX ? Need a register to compare NAME with VALUE>>,
					<<..IFIDN(POST,N)&..IFIDN(POST,L)>,<
						MOVX	AC,MASK
						TDNE	AC,LOC'Y>>,
					<<0>,<	MOVX	AC,MASK
						TDNN	AC,LOC'Y>>>)>>>)>>,
		<<..IFB(AC)>,<PRINTX ? Need a register to compare NAME with VALUE>>,
		<<0>,<..LOAD(AC,Y,LOC,MASK,NUMWDS,NAME,FLAGS,)
		.COND(<<<NUMWDS-1>,<CAX'POST AC,$$$VAL>>,
			<<NUMWDS-2>,<PRINTX ? Not yet>>,
			<<0>,<PRINTX ? Too many words to compare NAME with VALUE>>>)>>>)

%1:!
	SUPPRESS $$$LOC,$$$VAL,%1

	> ;; End of ...CFX definition

	...CFX	LIST

> ; End of ..CFX defintition
	SUBTTL	Macro definitions -- LSTOF. and LSTON.
 
 
;Macros to turn on and off listings with nesting and level control
;	LSTOF.			; Turns off listings only
;	LSTOF. XCREF		; Turns off listings and CREF
;	LSTON.			; Restores listings and CREF at top level
; If LSTIN. is defined as .MINFI then all listings are on
 
DEFINE	LSTOF.(FOO),<
	IFNDEF LSTIN.,LSTIN.==0 	;; Initialize level counter
IFE LSTIN.,<
	IFIDN <XCREF><FOO>,<.XCREF>	;; Conditionally suppress CREF
		   XLIST>		;; Turn off listings
	LSTIN.==LSTIN.+1>		;; Bump list level
 
DEFINE	LSTON.,<
	IFG LSTIN.,LSTIN.==LSTIN.-1	;; DECR list level
	IFLE LSTIN.,<.CREF		;; Resume CREFs
		      LIST>>		;; Resume lists
	SUBTTL	Macro definitions -- INTFLG & FLAG
 
;+
;.HL1 Miscellaneous macros
; These macros will do those repetitious things one normally used to have to
;do by hand, such as defining consecutive flags.
;.hl2 INTFLG and FLAG
; These macros will allow the easy generation of bit flags.
;-
;
;USAGE:
;	INTFLG	(PFX,MSK,CHR)	;PFX=SYMBOL PREFIX
;				;CHR=MIDDLE CHARACTER OF PRX<CHR>
;				;MSK=FIELD MASK (DEFAULT IS <-1>)
;	FLAG	(AAA)		;PFXAAA==FIRST FLAG
;	FLAG	(BBB)		;PFXBBB==SECOND FLAG
;	...
 
	DEFINE	INTFLG (PFX,MSK<-1>,CHR<$>)
<	.BIT. <==LFTBT.(MSK)>
	DEFINE	FLAG (NAM)
 <	DEFSM.(PFX'CHR''NAM,<.BIT.>)
	SUPPRES	BIT$$$
	SHOW.	<<PFX'CHR''NAM>>
   IFN MSK+1, IFN PFX'CHR''NAM&<-MSK-1>, PRINTX ? Flag mask for PFX'CHR''NAM exceeded
   IFE MSK+1, IFE PFX'CHR''NAM, PRINTX ? Flag mask for PFX'CHR''NAM exceeded
  >
	.XCREF	.BIT.,BIT$$$
>
	SUBTTL	Macro definitions -- INTNUM & NUM
 
;INTNUM & NUM - MACROS TO DEFINE CONSECUTIVE NUMBERS
;
;USAGE:
;	INTNUM	(PFX,VAL,MSK,CHR)	;PFX=SYMBOL PREFIX
;				;VAL=INITIAL VALUE (ZERO IS DEFAULT)
;				;CHR=BEGINNING CHARACTER
;				;MSK=FIELD MASK (DEFAULT IS <-1>)
;	NUM	(XXX)		;PFXXXX=FIRST NUMBER
;	NUM	(YYY)		;PFXYYY=FIRST NUMBER PLUS ONE
;	...
 
	DEFINE	INTNUM (PFX,VAL<0>,MSK<-1>,CHR<$>)
<	.INT. <==VAL>
	DEFINE	NUM (NAM,SIZ<1>)
  <	DEFSM.(CHR'PFX''NAM,<.INT. (,SIZ)>)
	SHOW.	<<CHR'PFX''NAM>>
   IFN MSK+1, IFN CHR'PFX''NAM&<-<MSK_-<ALIGN. (MSK)>>-1>, PRINTX ? NUM field for CHR'PFX'xxx symbols exceeded with symbol CHR'PFX''NAM
	SUPPRES	INT$$$			;; Suppress this symbol
 > 
	.XCREF	.INT.,INT$$$		;; Dont CREF these symbols
	DEFINE	ENDNUM(NAM<MAX>)<
	    DEFSM.(CHR'PFX''NAM,<.INT.(,0)>)
	    CHR'PFX''NAM==CHR'PFX''NAM-1
	    PURGE NUM,ENDNUM
	>;; End of ENDNUM macro definition
>
SUBTTL	Macro definitions -- .BIT.
 
 
;BIT - MACRO TO DEFINE CONSECUTIVE BIT POSITIONS
;
;USAGE:
;	.BIT. ==1BN		;FIRST BIT WILL BE 1BN
;	.BIT.			;HAS VALUE OF NEXT BIT
;	.BIT._N			;NEXT BIT SHIFTED N PLACES
;				;(DOES NOT AFFECT VALUE OF .BIT.)
 
	DEFINE	.BIT. (V)
<IFNB<V><BIT$$$'V>+IFB<V>,<IFN BIT$$$,<<<BIT$$$==BIT$$$_-1>_1>+<IFE BIT$$$,<1>>>>>
 
	SUBTTL	Macro definitions -- .INT.
 
;+
;.hl2 _.INT.
; This macro will define sucessive integers.  If this macro is called with
;no arguments, then it will return the sucessive integer.  If the first is
;used then it will append that to the internal symbol, this will allow the
;initialization of the macro.  The second argument is for defining the
;increment.  This is normally defaults to one.
;-
;
;USAGE:
;	.INT. ==N		; First integeter will be N
;	.INT.			; Return the next integer
;	.INT.+N			; Value of the next integer plus N
;				; (Does not affect the value of .INT.)
 
	DEFINE .INT. (V,XXX<1>)
<IFB<V>,<<INT$$$==INT$$$+XXX>-XXX>IFNB<V>,<INT$$$'V>>
	SUBTTL	Macro definitions -- BITMSK
 
;+
;.hl2 BITMSK
; This macro will generate a bit mask for the values given.
;-
;Usage:
;	BITMSK	(NAME,PREFIX,<XXX,YYY,ZZZ>)
; NAME is the name of the symbol to define as the bit mask
; <XXX,YYY,ZZZ> are the values to be masked
 
 
;Used as follows:
;	MOVX	AC,NAME		; Get the mask
;	LSH	AC,(VAL)	; VAL contains the value to check
;	JUMPL	AC,SUCCED	; Jump if value was in mask
 
 
	DEFINE	BITMSK(SYMBOL,PREFIX,NUMBERS),<
	SYMBOL==0		; SET SYMBOL TO ZERO
	IRP <NUMBERS>,<
		SYMBOL==SYMBOL!<1B<PREFIX'NUMBERS>>
	>>
	SUBTTL	Macro definitions -- Character masks

;+
;.hl1 Character mask macros
; The following set of macros will define a four word bit map, with
;each bit corresponding to a single ascii character.  Only the first
;32 bits of each word are used.  This is compatible with the corresponding
;macro in MACSYM, the usage of character masks in TOPS-20 JSYS's, and
;the usage in TECO.
;
;.hl2 BRINI$
; This macro will initialize the masks.
;.literal
;
; Usage:
;	BRINI$(NAME)
;
; Where: NAME is the name to be used for building the mask. It should not
;	 be more than 3 characters, as it is used to generate symbol names.
;
;.end literal
;-

	BRLEN$==4		; Length of the mask
	BRBPW$==^D32		; Bits per word

DEFINE BRINI$(NAME,INIT),<
	IFNB <INIT>,<
		%.0'NAME==%.0'INIT ;; Copy the initial values (if any)
		%.1'NAME==%.1'INIT
		%.2'NAME==%.2'INIT
		%.3'NAME==%.3'INIT
	> ;; End of IFNB <INIT>
	IFB <INIT>,<
		%.0'NAME==<%.1'NAME==0> ;; If no initial value, use 0
		%.2'NAME==<%.3'NAME==0>
	> ;; End of IFB <INIT>
> ; End of DEFINE BRINI$

;; Now define the macros for adding an removing characters

DEFINE BRKCH$(NAME,FIRST,LAST)<
	$$$VAL==FIRST
	$$$VL1==FIRST
	IFNB <LAST>,<$$$VL1==LAST>
	.XCREF $$$VAL,$$$VL1
	BRK$$$(NAME,$$$VAL,$$$VL1,!)
	SUPPRESS $$$VAL,$$$VL1
> ;; End of BRKCH$

DEFINE UNBRK$(NAME,FIRST,LAST)<
	$$$VAL==FIRST
	$$$VL1==FIRST
	IFNB <LAST>,<$$$VL1==LAST>
	.XCREF $$$VAL,$$$VL1
	BRK$$$(NAME,$$$VAL,$$$VL1,&^-)
	SUPPRESS $$$VAL,$$$VL1
> ;; End of UNBRK$



DEFINE BRK$$$(NAME,FIRST,LAST,OP)<
	$$$FST==FIRST		;; Get initial value
	$$$LST==LAST		;; Get final value
	.XCREF $$$FST,$$$LST
	REPEAT $$$LST-$$$FST+1,<
		$$$WRD==$$$FST/BRBPW$	;; Determine which word gets this char
		$$$BIT==$$$FST-<$$$WRD*BRBPW$> ;; And determine the bit
		IFE $$$WRD-BRLEN$,<	;; Special 'char' for TECO?
			$$$WRD==3	;; Yes, put in 3rd word
			$$$BIT==$$$BIT+BRBPW$ ;; After 32'nd bit
		> ;; End of IFE $$$WRD-BRLEN$
		BR$$$$(NAME,\"<$$$WRD+"0">,$$$BIT,OP)
		$$$FST==$$$FST+1
	> ;; End of REPEAT
> ; End of BRK$$$

DEFINE BR$$$$(NAME,WORD,BIT,OP)<%.'WORD'NAME==%.'WORD'NAME'OP'1B<BIT>>


DEFINE BRGEN$(NAME)<EXP %.0'NAME,%.1'NAME,%.2'NAME,%.3'NAME>

DEFINE BRWRD$(NAME,INDEX),<%.'INDEX'NAME>


; Now generate some common masks

	BRINI$(ALL)			; All characters
	BRKCH$(ALL,0,177)		;  .  .  .

	BRINI$(ALP)			; Alphabetics
	BRKCH$(ALP,"A","Z")
	BRKCH$(ALP,"a","z")
	SUBTTL	Macro definitions -- FALL

;+
;.HL1 FALL
;This macro will check to see that a routine is falling into another routine.
;.literal
;
; Usage:
;	FOO:	<Routine>
;		FALL	BAR
;	BAR:
;.end literal
;-

DEFINE	FALL(ROUTINE),<
IF2,<IFN .-ROUTINE,<PRINTX ? Can not fall into ROUTINE>>
> ; End of FALL macro definition
	SUBTTL	Macro definitions -- TABDEF, TABENT, TABEND
 
;+
;.hl2 TABDEF, TABENT and TABEND
; These macros are useful for generating tables.  TABDEF will initialize
;the table.  TABENT inserts an entry into the table with the specified offset
;and TABEND will end the table.
;-
;
; Usage:
;
;	TABDEF	XXX,YY,Default.value
;
; Will generate xxxTBL.  It will also expect a yyyMAX to be defined.
;
;	TABENT	ZZZ,<VALUE>
;
; At yyy'zzz+xxxTBL location the value will be generated.
;
;	TABEND
;
; This will end the current table
 
 
DEFINE	TABDEF(NAME,SYM,DEFAULT)<
    IFDEF TABENT,<PRINTX ? TABDEF missing TABEND before "TABDEF NAME,SYM,DEFAULT">
    DEFINE  TABENT(OFF,VALUE)<
	.ORG	NAME'TBL+SYM''OFF
	VALUE
    >
    DEFINE  TABEND<
	.ORG	NAME'TBL+1+SYM'MAX
	PURGE	TABEND,TABENT
    >
 
NAME'TBL:XLIST
    IFNB <DEFAULT><REPEAT SYM'MAX+1,<EXP DEFAULT>>
	LIST
>
	SUBTTL	Macro definitions -- BITON & BITOFF
 
;+
;.hl2 BITON and BITOFF
; These macros are used to turn bits on and off in memory.  They will use
;T1 as the register to use if none has been specified.
;These macros will leave the AC containing any bits that are on in the location
;-
;
; Usage:
;
;	BITON	T2,SB$XXX,$SIFLG(T1)	; Turns SB$XXX bits off in $SIFLG(T1)
 
 
DEFINE	BITON(AC<T1>,BIT,LOC)<
	MOVX	AC,BIT
	IORB	AC,LOC
>
 
DEFINE	BITOFF(AC<T1>,BIT,LOC)<
	MOVX	AC,BIT
	ANDCAB	AC,LOC
>
	SUBTTL	Macro definitions -- Stack control (FRAME.)
 
;Macro to define a bunch of words on the stack.
;Each argument to the FRAME. macro allocates one word on the stack
;and defines a macro with the same name as -N(P).
 
;WARNING: This macro defines things in terms of (P) and therefor
;	  nothing else may be PUSHed on the stack !
 
DEFINE	FRAME. (LIST,%A),<
	
    .XCREF			;; Turn off cross reference

    DEFINE FR%AME(ITEM)<FR%%AM(ITEM)> ;; To remove angle brackets

    DEFINE FR%%AM(A,B<1>),<
	FR%%%A(A,\<N%%%+1>)	;; Define the item
	N%%%==N%%%+B		;; Point to the next offset
    >; End of FR%%AM macro definition

    DEFINE FR%%%A(NAME,OFFSET)<
	DEFINE	NAME<-^O<OFFSET>(P)>
    >;; End of FR%%%A macro definition

    .XCREF FR%AME, FR%%AM, FR%%%A ;; Don't cref
    .CREF			;; Turn this back on again

    OLD%%%==10			;; Save current radix
    .XCREF OLD%%%		;; Remove this symbol
    RADIX  8			;; Set the radix to 8
    N%%%==0			;; Initialize the argument count
    .XCREF N%%%			;; Keep this out of the CREF
    IRP LIST,<
	FR%AME	(LIST)		;; Define the symbol macro and increment
				;;  the counter
    >;; End of IRP LIST
	ADJSP	P,N%%%		;; Allocate the space
	PUSHJ	P,%A		;; Do the subroutine
	  SKIPA
	AOS	-N%%%(P)	;; Pass on the skip return
	ADJSP	P,-N%%%		;; Deallocate the space
	POPJ	P,		;; Return
%A:!
	.XCREF	%A		;; Remove this from the CREF also
	RADIX	OLD%%%
	PURGE	N%%%,OLD%%%
	PURGE	FR%AME, FR%%AM, FR%%%A
>
	SUBTTL	Macro definitions -- JUMPPT
 
;MACRO TO JUMP DEPENDING UPON PROCESSOR TYPE
 
;CALL:	JUMPPT	TEMPAC,PDP-6 ADDR,KA-10 ADDR,KI-10 ADDR,KL-10 ADDR
;	WHERE	TEMPAC IS AN AC TO USE AS A TEMP
;	BLANK PROCESSORS FALL THROUGH TO NEXT INSTRUCTION
 
DEFINE	JUMPPT	(AC,CP166,KA10,KI10,KL10,KX,KY,KZ,%1),<
IFDIF <CP166><KA10>,<
	JFCL	1,.+1		;;CLEAR PC-CHANGE FLAG
	JRST	.+1		;;SET PC-CHANGE
IFNB <CP166>,<	JFCL	1,CP166
  IFNB <KA10>,<IFIDN <KA10><KI10>,<IFIDN <KI10><KL10>,< JRST	KA10>>>>
IFB <CP166>,<	JFCL	1,%1
  IFIDN <KA10><KI10>,<IFIDN <KI10><KL10>,< JRST	KA10>>>
>;;END IFDIF <CP166><KA10>
 
IFDIF <KA10><KI10>,<
	HRLOI	AC,-2		;;SET FOR KA/KI TEST
IFNB <KA10>,<	AOBJP	AC,KA10
  IFNB <KI10>,<IFIDN <KI10><KL10>,<JRST	KI10>>>
IFB <KA10>,<IFDIF <KI10><KL10>,<AOBJP AC,%1>
	    IFIDN <KI10><KL10>,<AOBJN AC,KI10>>
>;;END IFDIF <KA10><KI10>
 
IFDIF <KI10><KL10>,<
	IF2,<IFE AC,<PRINTX ? AC MUST BE NON-ZERO IN JUMPPT>>
	MOVEI	AC,0		;;SET FOR KI/KL TEST
	BLT	AC,0		;;DO TEST
IFNB <KI10>,<	JUMPE	AC,KI10
  IFNB <KL10>,<	JRST	KL10>>
IFB <KI10>,<	JUMPN	AC,KL10>
>;;END IFDIF <KI10><KL10>
 
%1:>
 
; Define the units of storage allocation
 
.SUAKA==^D1024			; KA-10 processor
.SUAKI==^D512			; KI-10 processor
.SUAKL==^D512			; KL-10 processor
.SUAKS==^D512			; KS-10 processor
	SUBTTL	Useful OPDEFS
 
	OPDEF	PJRST	[JUMPA 17,]	; PUSHJ/POPJ
	OPDEF	PJRSTF	[JRSTF]		; PUSHJ/POPJ
	OPDEF	PJSP	[JSP]		; MOVEI .+1/PUSHJ/POPJ
	OPDEF	PJUMPL	[JUMPL]
	OPDEF	PJMPLE	[JUMPLE]
	OPDEF	PJUMPE	[JUMPE]
	OPDEF	PJUMPN	[JUMPN]
	OPDEF	PJUMPG	[JUMPG]
	OPDEF	PJMPGE	[JUMPGE]

; Opdefs not known to DDT

; JRST xx,

	OPDEF	PORTAL	[JRST	01,] 	; Concealed entry point jump
	OPDEF	JRSTF	[JRST	02,]	; Jump restoring flags
	OPDEF	HALT	[JRST	04,]	; Jump, halting processor
	OPDEF	XJRSTF	[JRST	05,] 	; Extended addressing JRSTF
	OPDEF	XJEN	[JRST	06,]	; Extended addressing JEN
	OPDEF	XPCW	[JRST	07,]	; Extended addressing XSFM+XJRSTF
	OPDEF	JEN	[JRST	12,]	; JRSTF enabling PI
	OPDEF	SFM	[JRST	14,]  	; Extended addressing save flag PC, no jump

; JFCL xx,

	OPDEF	JFOV	[JFCL	01,]	; Jump on floating under/overflow
	OPDEF	JCRY1	[JFCL	02,]	; Jump on carry-1
	OPDEF	JCRY0	[JFCL	04,]	; Jump on carry-0
	OPDEF	JCRY	[JFCL	06,]	; Jump on carry-0 or carry-1
	OPDEF	JOV	[JFCL	10,]	; Jump on overflow

; Other extended addressing opdefs

	OPDEF	XMOVEI	[SETMI]
	OPDEF	XBLT	[20B8]
	OPDEF	XHLLI	[HLLI]
 
; Extended addressing macro definitions
 
	OPDEF	IFIW	[1B0]
	.NODDT	IFIW			; No output to DDT
 
DEFINE	GIW(I,ADDRESS,IDX<0>),<INSVL.(0,GW.ZER)!INSVL.(<IFNB <I>,<-1>>,GW.IND)!INSVL.(IDX,GW.IDX)!INSVL.(ADDRESS,GW.ADR)>
	SUBTTL	Symbols for the control characters
 
	.CHCAT==000		; Control atsign (@) (Null)
	.CHCNA==001		; Control A
	.CHCNB==002		; Control B
	.CHCNC==003		; Control C
	.CHCND==004		; Control D
	.CHCNE==005		; Control E
	.CHCNF==006		; Control F
	.CHCNG==007		; Control G (Bell)
	.CHCNH==010		; Control H (Backspace)
	.CHCNI==011		; Control I (Tab)
	.CHCNJ==012		; Control J (Line feed)
	.CHCNK==013		; Control K (Vertical tab)
	.CHCNL==014		; Control L (Form feed)
	.CHCNM==015		; Control M (Carriage return)
	.CHCNN==016		; Control N
	.CHCNO==017		; Control O
	.CHCNP==020		; Control P
	.CHCNQ==021		; Control Q
	.CHCNR==022		; Control R
	.CHCNS==023		; Control S
	.CHCNT==024		; Control T
	.CHCNU==025		; Control U
	.CHCNV==026		; Control V
	.CHCNW==027		; Control W
	.CHCNX==030		; Control X
	.CHCNY==031		; Control Y
	.CHCNZ==032		; Control Z
	.CHCLB==033		; Control left bracket
	.CHCBS==034		; Control back slash
	.CHCRB==035		; Control right bracket
	.CHCCF==036		; Control circonflex
	.CHCUN==037		; Control underline

; Symbols with ASCII names for control characters

	.CHNUL=000		; Null (tape feed character, fill character)
	.CHSOH==001		; Start of header
	.CHSTX==002		; Start of text
	.CHETX==003		; End of text
	.CHEOT==004		; End of transmission
	.CHENQ==005		; Enquiry (WRU "Who are you?")
	.CHACK==006		; Acknowledge
	.CHBEL==007		; Bell
	.CHBS== 010		; Backspace
	.CHHT== 011		; Horizontal tab
	.CHLF== 012		; Line feed
	.CHVT== 013		; Vertical tab
	.CHFF== 014		; Form feed
	.CHCR== 015		; Carriage return
	.CHSO== 016		; Shift out
	.CHSI== 017		; Shift in
	.CHDLE==020		; Data link escape
	.CHDC1==021		; Device control 1 (also XON)
	.CHDC2==022		; Device control 2 (also TAPE or AUX ON)
	.CHDC3==023		; Device control 3 (also XOFF)
	.CHDC4==024		; Device control 4 (also AUX OFF)
	.CHNAK==025		; Negative acknowledge
	.CHSYN==026		; Synchronous idle (SYNC)
	.CHETB==027		; End of transmission block
	.CHCAN==030		; Cancel
	.CHEM== 031		; End of medium
	.CHSUB==032		; Substitute
	.CHESC==033		; Escape
	.CHFS== 034		; File separator
	.CHGS== 035		; Group separator
	.CHRS== 036		; Record separator
	.CHUS== 037		; Unit separator
 
	.CHALT==175		; Old altmode
	.CHAL2==176		; Other type of old altmode
	.CHDEL==177		; Delete

; Alternate names for motion characters

	.CHTAB==.CHHT		; Tab
	.CHLFD==.CHLF		; Line feed
	.CHVTB==.CHVT		; Vertical tab
	.CHFFD==.CHFF		; Form feed
	.CHCRT==.CHCR		; Carriage return
	SUBTTL	Hardware bits of interest to users
 
;PC Flags
 
	PC.OVF==1B0		; Overflow
	PC.CY0==1B1		; Carry 0
	PC.CY1==1B2		; Carry 1
	PC.FOV==1B3		; Floating overflow
	PC.BIS==1B4		; Byte increment suppression
	PC.USR==1B5		; User mode
	PC.UIO==1B6		; User IOT mode
	PC.LIP==1B7		; Last instruction public
	PC.AFI==1B8		; Address failure inhibit
	PC.ATN==3B10		; APR trap number
	PC.FUF==1B11		; Floating underflow
	PC.NDV==1B12		; No divide
	SUBTTL	End of MAC
 
	END			; End of MAC