;Random useful coding macros. GZ@OZ developed MACSYM.MID based on the
;Twenex monitor macro collection MACSYM.MAC - this is a non-Twenex-specific
;subset of that.

;Stuff supported (will add more stuff as need arises):
; FLD(VAL,MSK) & BIT(n) & POINT SIZE,ADDR,OFFSET
; MOVX AC,MASK & TXxx AC,MASK & JXx AC,MASK,ADDR & LOAD/STOR AC,MASK,ADDR
; DO./ENDDO. macros (and related stuff)
; IFxxx/ANxxx macros
; SAVEACS [A,B,C,D] & SAVE. [LOC,LOC,LOC]


.KILL  ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3,TOP.
.XCREF ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3
.XCREF ..DX,..IX,..EX,.SAVX1,.SAVX2

IF2,.INEOF			;Don't bother if no code

;.NSTGW				;No storage words in this part

DEFINE FLD (VAL,MASK)
<.DPB <VAL>,<.BP <MASK>,>,0>TERMIN

DEFINE BIT (N)
<1_<35.-<N>>>TERMIN

DEFINE POINT SIZE=7,ADDR=0,COUNT=0
RADIX 8+2
..X1==SIZE
..X2==COUNT
RADIX 8
..XX==<..X2-1>/<36./..X1>
..X2==..X2-..XX*<36./..X1>
<<<36.-<..X1*..X2>>_30.>+<..X1_24.>+<ADDR>+..X1>
TERMIN

;MOVX - LOAD AC WITH CONSTANT

DEFINE MOVX AC,#MSK
   IFE <-1,,0>&MSK,[MOVEI AC,MSK]
   .ELSE [IFE <0,,-1>&MSK,[MOVSI AC,(MSK)]
	  .ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[HRROI AC,MSK]
		 .ELSE [IFE <<0,,-1>&MSK>-<0,,-1>,[HRLOI AC,(MSK&.LHALF)]
			.ELSE [MOVE AC,[MSK]]]]]
TERMIN

;TX - TEST MASK

IRP OP,,[N,NA,OE,ON,OA,ZE,ZN,ZA,CE,CN,CA]
  DEFINE TX!OP AC,#MSK
    IFE <-1,,0>&MSK,[TR!OP AC,MSK]
    .ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)]
	   .ELSE [TD!OP AC,[MSK]]]
  TERMIN
TERMIN

IRP OP,,[N,E]
  DEFINE TXN!OP AC,#MSK
    IFE <-1,,0>&MSK,[TRN!OP AC,MSK]
    .ELSE [IFE <0,,-1>&MSK,[TLN!OP AC,(MSK)]
	   .ELSE [IFE MSK+1,[CAI!OP AC,0]
		  .ELSE [TDN!OP AC,[MSK]]]]
  TERMIN
TERMIN

..TXZ==ANDI
..TXO==ORCMI
..TXC==EQVI
IRP OP,,[Z,O,C]
  DEFINE TX!OP AC,#MSK
    IFE <-1,,0>&MSK,[TR!OP AC,MSK]
    .ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)]
	   .ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[..TX!OP AC,-1#MSK]
		  .ELSE [TD!OP AC,[MSK]]]]
  TERMIN
TERMIN

EQUALS IORX,TXO
EQUALS XORX,TXC

DEFINE ANDX AC,#MSK
TXZ AC,-1#MSK
TERMIN

	SUBTTL JX -- JUMP ON MASK

;JXE -- JUMP IF MASKED BITS ARE EQUAL TO 0
;JXN -- JUMP IF MASKED BITS ARE NOT EQUAL TO 0
;JXO -- JUMP IF MASKED BITS ARE ALL ONES
;JXF -- JUMP IF MASKED BITS ARE NOT ALL ONES (FALSE)

DEFINE JXE AC,#MSK,?ADR
 IFE MSK-.MINFI,[JUMPGE AC,ADR]
 .ELSE [IFE MSK+1,[JUMPE AC,ADR]
	.ELSE [TXNN AC,MSK
		JRST ADR]]
TERMIN

DEFINE JXN AC,#MSK,?ADR
 IFE MSK-.MINFI,[JUMPL AC,ADR]
 .ELSE [IFE MSK+1,[JUMPN AC,ADR]
	.ELSE [TXNE AC,MSK
		JRST ADR]]
TERMIN

DEFINE JXO AC,#MSK,?ADR
 IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXN AC,MSK,ADR]
 .ELSE [TXC AC,MSK
	TXCN AC,MSK
	  JRST ADR]
TERMIN

DEFINE JXF AC,#MSK,?ADR
IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXE AC,MSK,ADR]
.ELSE [TXC AC,MSK
       TXCE AC,MSK
	JRST ADR]
TERMIN

;LOAD, STOR
DEFINE LOAD AC,#MSK,?LOCN
  IFE MSK+1,[MOVE AC,LOCN]
  .ELSE [IFE MSK-777777,[HRRZ AC,LOCN]
	.ELSE [IFE MSK-<-1,,0>,[HLRZ AC,LOCN]
		.ELSE [LDB AC,[.BP MSK,LOCN]]]]
TERMIN

DEFINE STOR AC,#MSK,?LOCN
 IFE MSK+1,[MOVEM AC,LOCN]
 .ELSE [IFE MSK-777777,[HRRM AC,LOCN]
	.ELSE [IFE MSK-<-1,,0>,[HRLM AC,LOCN]
		.ELSE [DPB AC,[.BP MSK,LOCN]]]]
TERMIN

	SUBTTL BLOCK MACROS

;MACROS TO PROVIDE SOME BLOCK HANDLING OF CODE

;DO. - LOOP STRUCTURE, DECLARES TOP OF LOOP
; LOOP. - JUMPS TO TOP OF LOOP
; EXIT. - EXITS LOOP
; TOP. - TAG AT TOP OF LOOP FOR JUMPS, E.G. SOJG T4,TOP.
; ENDLP. - TAG AT END OF LOOP FOR JUMPS, E.G. SOJL T4,ENDLP.

DEFINE DO.
   ..DX
TERMIN

DEFINE ..DX \%TGE,%SV1,%SV2,%SV3
	EQUALS %SV1,TOP. ? EQUALS %SV2,ENDDO. ? EQUALS %SV3,ENDLP.
	.KILL %SV1
	TOP.==.
	DEFINE ENDDO.
	 %TGE::EQUALS TOP.,%SV1 ? EQUALS ENDDO.,%SV2 ? EQUALS ENDLP.,%SV3
	 .KILL %TGE
	TERMIN
	DEFINE ENDLP.
%TGE!!TERMIN
TERMIN

DEFINE ENDDO.
.ERR ENDDO. outside loop
TERMIN
DEFINE ENDLP.
.ERR ENDLP. outside loop
TERMIN
TOP.==-1

DEFINE OD.
ENDDO.!TERMIN

DEFINE LOOP.
JRST TOP.!TERMIN

DEFINE EXIT.
JRST ENDLP.!TERMIN


;Conditionals

DEFINE IFSKP.
..IX [JRST ]
TERMIN

DEFINE IFNSK.
TRNA
 ..IX [JRST ]
TERMIN

DEFINE IFXN. AC,#MASK
 IFE 1_35.-MASK,..IX [JUMPGE AC,]
 .ELSE [IFE MASK+1,..IX [JUMPE AC,]
       .ELSE [TXNN AC,MASK
		..IX [JRST ]
	     ]]
TERMIN

DEFINE IFXE. AC,#MASK
 IFE 1_35.-MASK,..IX [JUMPL AC,]
 .ELSE [IFE MASK+1,..IX [JUMPN AC,]
       .ELSE [TXNE AC,MASK
		..IX [JRST ]
	     ]]
TERMIN

DEFINE IFE. AC
..IX [JUMPN AC,]
TERMIN

DEFINE IFN. AC
..IX [JUMPE AC,]
TERMIN

DEFINE IFG. AC
..IX [JUMPLE AC,]
TERMIN

DEFINE IFGE. AC
..IX [JUMPL AC,]
TERMIN

DEFINE IFLE. AC
..IX [JUMPG AC,]
TERMIN

DEFINE IFL. AC
..IX [JUMPGE AC,]
TERMIN

DEFINE ..IX OP,\%TAG,%SV1,%SV2
	OP!%TAG
	EQUALS %SV1,..TG ? EQUALS %SV2,ENDIF.
	DEFINE ..TG LBL
	%TAG!!LBL!TERMIN
	DEFINE ENDIF.
	..TG [::]
	.KILL ..TG
	 EQUALS ..TG,%SV1 ? EQUALS ENDIF.,%SV2
	TERMIN
TERMIN

DEFINE ELSE.
..EX
TERMIN

DEFINE ..EX \%TAG
	JRST %TAG
	..TG [::]
	DEFINE ..TG LBL
	  %TAG!!LBL!TERMIN
TERMIN

DEFINE ..TG LBL
 .ERR Conditional construct outside a conditional
TERMIN

DEFINE ENDIF.
 .ERR ENDIF. outside a conditional
TERMIN


;GENERAL CASES WITHIN CONDITIONALS

DEFINE ANSKP.
  JRST ..TG
TERMIN

DEFINE ANNSK.
	TRNA
	  JRST ..TG
TERMIN

DEFINE ANDXN. AC,#MASK
IFE 1_35.-MASK,JUMPGE AC,..TG
.ELSE [IFE MASK+1,JUMPE AC,..TG
       .ELSE [TXNN AC,MASK
		JRST ..TG
	     ]]
TERMIN

DEFINE ANDXE. AC,#MASK
IFE 1_35.-MASK,JUMPL AC,..TG
.ELSE [IFE MASK+1,JUMPN AC,..TG
       .ELSE [TXNE AC,MASK
		JRST ..TG
	     ]]
TERMIN

DEFINE ANDE. AC
	JUMPN AC,..TG
TERMIN

DEFINE ANDN. AC
	JUMPE AC,..TG
TERMIN

DEFINE ANDG. AC
	JUMPLE AC,..TG
TERMIN

DEFINE ANDGE. AC
	JUMPL AC,..TG
TERMIN

DEFINE ANDLE. AC
	JUMPG AC,..TG
TERMIN

DEFINE ANDL. AC
	JUMPGE AC,..TG
TERMIN



; SAVEAC [A,B,C]
; Supports +1/+2 returns.
; Unlike macro version, supports arbitrary locations (not just AC's)
; and doesn't clobber AC16. Assumes stack in P, though.

DEFINE SAVEAC ACS
	IRP AC,,[ACS]
	  PUSH P,AC
	  ..XX==.IRPCNT
	TERMIN
	.SAVX1 ..XX+1,[ACS]
TERMIN

EQUALS SAVE.,SAVEAC		;Not in MACRO version...

DEFINE .SAVX1 #N#,ACS
	PUSH P,[[CAIA
		   AOS -N(P)
		 .SAVX2 [ACS]
		 POPJ P,
		]]
TERMIN

DEFINE .SAVX2 ACS
	IRP AC,REST,[ACS]
	  .SAVX2 [REST]
	  POP P,AC
	  .ISTOP
	TERMIN
TERMIN

