; mxa.asm -- Midas/Maxc2 interface procedures
;		E. R. Fiala and E. A. Taft / March 1976
; !!!!!!!! Warning -- These procedures are not reentrant !!!!!!!!!!

.ent XctR4		; Read registers of various sizes
.ent XctR8
.ent XctR9
.ent XctR12
.ent XctR18
.ent XctR20
.ent XctR36

.ent XctL4		; Write registers of various sizes
.ent XctL8
.ent XctL9
.ent XctL12
.ent XctL18
.ent XctL20
.ent XctL36

.ent XctMic		; Execute a microinstruction

.ent RestoreMRegs	; Restore registers after memory read/write
.ent ConvertAV		; Unpack AddrVec into MADDRL and MADDRH
			; and load registers to address memory

.ent SetIMLd
.ent SetIMRd

.ent ZeroCore

.ent ADREG		; Indirect word for SMI address register
.ent INREG		; Indirect word for SMI input
.ent OUTREG		; Indirect word for SMI output

.ent LDRMEM		; Points at word 0 of LDR memory
.ent ITRCNT		; LDR COUNT
.ent INSTST		; LDR TSTINS
.ent MEMCFG		; LDR CONFIG
.ent ADRANG		; LDR ARANGE
.ent GOODD		; Test write data
.ent ACTD		; Test read data
.ent DMASK		; Test comparison mask
.ent RANDATA		; Static for random number generator
.ent RANDIX		; Another random number generator static
.ent PATTERN		; Index for data test pattern
.ent LOWADDR		; Low address for memory tests
.ent HIGHADDR		; High address for memory tests
.ent TAVEC		; Address vector for memory tests
.ent TestWidth		; Width of register or memory being tested
.ent REGACT		; Vector of register actions
.ent MEMACT		; Vector of memory actions
.ent PATACT		; Vector of pattern actions
.ent QUITact		; Action static for abort
.ent QuitF		; EveryTimeList static
.ent TMP		; Four-word vectors beginning at even words
.ent TMP1
.ent TMP2
.ent CUM		; Three-word vector containing 36-bit 400

.ent SMFORF		; Vector holding value for SMFORF = SM 377
.ent F			; Vector holding value for F
.ent Q			; Vector holding value for Q
.ent EREG		; Vector holding value for EREG
.ent STK		; Vector holding 12 STK registers

.ent NPC		; Static holding value for NPC
.ent IMA		; Static holding value for IMA
.ent Y			; Static holding value for Y
.ent X			; Static holding value for X

.ent MADDRL		; Static holding low 16 bits of memory address
.ent MADDRH		; Static holding high 16 bits of memory address
.ent LADDR		; Static holding LDR displacement for MADDRL
.ent MAINsize		; Static holding max. MADDRH for MAIN

.ent MEMNAM		; Table of memory names
.ent MName
.ent MEMWID		; Table of memory widths
.ent MEMFORMS		; Table of memory output format vectors
.ent MForm
.ent MEMLEN		; Table of memory lengths
.ent REGNAM		; Table of register names
.ent RName
.ent REGWID		; Table of register widths
.ent REGFORMS		; Table of register output format vectors
.ent RForm

B0 = 203		; SMI addresses
B1 = 202
B2 = 201
CR = 210
BR0 = 213
BR1 = 212
BR2 = 211
PIR0 = 217
PIR1 = 216
PIR2 = 215
PIR3 = 214

BRNIMA = 151		; Addresses in LDRMEM of microinstructions
LDX = 170
LDY = 202
LDQ = 214
SETFLY = 221
LDNPC = 226
LDEREG = 303
LDSMF = 322
CLRFLY = 327
SETFLQ = 334
CLRFLQ = 341

LDRSIZE = 130		; Size of LDR memory

.TXTM B

.srel

XctMic:		.XctMic

XctR4:		.XctR4
XctR8:		.XctR8
XctR9:		.XctR9
XctR12:		.XctR12
XctR18:		.XctR18
XctR20:		.XctR20
XctR36:		.XctR36

XctL4:		.XctL4
XctL8:		.XctL8
XctL9:		.XctL9
XctL12:		.XctL12
XctL18:		.XctL18
XctL20:		.XctL20
XctL36:		.XctL36

RestoreMRegs:	.RestoreMRegs
ConvertAV:	.ConvertAV

SetIMLd:	.SetIMLd
SetIMRd:	.SetIMRd

ZeroCore:	.ZeroCore

; **This method of definition only works if all references to the
; statics occur after the definitions**
MForm:	Form36
	Form36
	FormIM
	Form36
	FormDM
	0
	Form40
	Form36
	Form36
	0
	FormDM
	FormDM
	FormLDR
	Form36

RForm:	0
	0
	0
	Form36
	Form36
	Form36
	0
	0
	Form40
	0
	Form40
	Form36
	0
	0
	Form36
	0
	Form36

MName:	IMhn
	IMln
	IMn
	SMn
	DMn
	MPn
	MAINn
	RMn
	LMn
	STKn
	DM1n
	DM2n
	LDRn
	KSTATn

RName:	Xn
	ACn
	Yn
	Pn
	Qn
	Fn
	NPCn
	MARn
	MDRn
	KMARn
	KMDRn
	ARMn
	IMAn
	KUNITn
	EREGn
	BPCn
	P1n

.zrel			; Page 0 stuff

ADREG:		177400	; SMI address register
INREG:		177401	; SMI input register
OUTREG:		177403	; SMI output register
; 177402 OUTREGP
; 177404 ERRINF
; 177405 ERRENB

LDRMEM:		0	; Vectors initialized by InitMpCode
ITRCNT:		0
INSTST:		0
MEMCFG:		0
ADRANG:		0
GOODD:		0
ACTD:		0
DMASK:		0
CUM:		.CUM
RANDATA:	0
RANDIX:		0
PATTERN:	0
LOWADDR:	0
HIGHADDR:	0
TAVEC:		0
TestWidth:	0
REGACT:		0
MEMACT:		0
PATACT:		0
QUITact:	0
QuitF:		0
TMP:		0
TMP1:		0
TMP2:		0

Q:		0	; Vectors for microprocessor state
F:		0
EREG:		0
SMFORF:		0
STK:		0

IMA:		0	; Statics for microprocessor state
NPC:		0
X:		0
Y:		0

LADDR:		0
MADDRL:		0
MADDRH:		0
MAINsize:	17

MEMNAM:		0
MEMLEN:		.MLen	; Table of memory lengths indexed by MemX
MEMWID:		.MWid
MEMFORMS:	0
REGNAM:		0
REGWID:		.RWid
REGFORMS:	0

.nrel

.CUM:	0
	20
	0

Form36:	2
	0
	22
	22
	22

Form40:	3
	0
	4
	4
	22
	26
	22

FormIM:	4
	0
	22
	22
	22
	44
	22
	66
	22

FormDM:	3
	0
	14
	14
	14
	30
	14

FormLDR: 5
	0
	10
	10
	22
	32
	22
	54
	22
	76
	22

IMhn:	.txt "IM[0,35]"
IMln:	.txt "IM[36,71]"
IMn:	.txt "IM"
SMn:	.txt "SM"
DMn:	.txt "DM"
MPn:	.txt "MP"
MAINn:	.txt "MAIN"
RMn:	.txt "RM"
LMn:	.txt "LM"
STKn:	.txt "STK"
DM1n:	.txt "DM1"
DM2n:	.txt "DM2"
LDRn:	.txt "LDR"
KSTATn:	.txt "KSTAT"

.MWid:	44
	44
	110
	44
	44
	22
	50
	44
	44
	14
	44
	44
	120
	44

Xn:	.txt "X"
ACn:	.txt "AC"
Yn:	.txt "Y"
Pn:	.txt "P"
Qn:	.txt "Q"
Fn:	.txt "F"
NPCn:	.txt "NPC"
MARn:	.txt "MAR"
MDRn:	.txt "MDR"
KMARn:	.txt "KMAR"
KMDRn:	.txt "KMDR"
ARMn:	.txt "ARM"
IMAn:	.txt "IMA"
KUNITn:	.txt "KUNIT"
EREGn:	.txt "EREG"
BPCn:	.txt "BPC"
P1n:	.txt "P1"

.RWid:	10
	4
	11
	44
	44
	44
	14
	24
	50
	24
	50
	44
	14
	3
	44
	24
	44

; Procedures to read registers of various widths

; XctR4(LdrAddr,DataVec)

.XctR4:
	sta 3 save3
	jsr .XctMR
	 1
	jmp XctRd


; XctR20(LdrAddr,DataVec)

.XctR20:
	sta 3 save3
	jsr .XctMR
	 1
	jmp XctRc


; XctR18(LdrAddr,DataVec)

.XctR18:
	sta 3 save3
	jsr .XctMR
	 1
	lda 3 save1
	lda 0 .B1
	sta 0 @ADREG
	lda 0 @INREG
	lda 1 .B2
	sta 1 @ADREG
	lda 1 @INREG
	coms 1 1
	movzl 1 1
	coml 0 0
	movl 1 1
	movl 0 0
	sta 0 0 3
	lda 0 c140000
	and 1 0
	sta 0 1 3
	jmp XctRb


; XctR8(LdrAddr,DataVec)

.XctR8:
	sta 3 save3
	jsr .XctMR
	 1
	lda 0 .B1
	sta 0 @ADREG
	lda 0 @INREG
	com 0 0
	lda 3 c17
	ands 3 0
	lda 1 .B2
	sta 1 @ADREG
	lda 1 @INREG
	com 1 1
	lda 3 c360
	and 3 1
	add 1 0
	cycle 4
	jmp XctRa

; XctR9(LdrAddr,DataVec)

.XctR9:
	sta 3 save3
	jsr .XctMR
	 1
	lda 0 .B1
	sta 0 @ADREG
	lda 0 @INREG
	com 0 0
	lda 3 c37
	ands 3 0
	lda 1 .B2
	sta 1 @ADREG
	lda 1 @INREG
	com 1 1
	lda 3 c360
	and 3 1
	add 1 0
	cycle 3
	jmp XctRa


; XctR12(LdrAddr,DataVec)

.XctR12:
	sta 3 save3
	jsr .XctMR
	 1
	lda 0 .B1
	sta 0 @ADREG
	lda 0 @INREG
	com 0 0
	lda 3 c377
	ands 3 0
	lda 1 .B2
	sta 1 @ADREG
	lda 1 @INREG
	com 1 1
	lda 3 c360
	and 3 1
	add 1 0
	jmp XctRa


; XctR36(LdrAddr,DataVec)

.XctR36:
	sta 3 save3
	jsr .XctMR
	 1
	lda 0 .B0
	sta 0 @ADREG
	lda 0 @INREG
	com 0 0
	sta 0 @save1
	isz save1
XctRc:	lda 0 .B1
	sta 0 @ADREG
	lda 0 @INREG
	com 0 0
	sta 0 @save1
	isz save1
XctRd:	lda 0 .B2
	sta 0 @ADREG
	lda 0 @INREG
	com 0 0
	lda 1 c360
	ands 1 0
XctRa:	sta 0 @save1
XctRb:	lda 3 save3
	jmp 1 3

c37:	37
c17:	17
c140000: 140000
c360:	360
.B0:	B0
.B1:	B1
.B2:	B2
save3:	0
save1:	0

; XctMic(LdrAddr) -- Execute a microinstruction

.XctMR:	sta 1 save1
.XctMic:
	sta 3 1 2
xctm1:	lda 3 LDRMEM		; Compute lv LDRMEM!LdrAddr
	add 0 3

	lda 1 .PIR0
	sta 1 @ADREG
	lda 1 0 3
	sta 1 @OUTREG

	lda 1 .PIR1
	sta 1 @ADREG
	lda 1 1 3	
	sta 1 @OUTREG

	lda 1 .PIR2
	sta 1 @ADREG
	lda 1 2 3
	sta 1 @OUTREG

	lda 1 .PIR3
	sta 1 @ADREG
	lda 1 3 3	
	sta 1 @OUTREG

	lda 1 .CR
	sta 1 @ADREG
	lda 1 4 3
	com 1 1			; Complement the control signals
	sta 1 @OUTREG

	lda 3 1 2
	jmp 1 3

.PIR0:	PIR0
.PIR1:	PIR1
.PIR2:	PIR2
.PIR3:	PIR3
.CR:	CR
.BR0:	BR0
.BR1:	BR1
.BR2:	BR2
c77000:	77000
c17740:	17740
c377:	377

; Procedures to load registers of various widths

; XctL4(LdrAddr,DataVec)

.XctL4:
	sta 3 1 2
	mov 1 3
	jmp XctLa


; XctL20(LdrAddr,DataVec)

.XctL20:
	sta 3 1 2
	mov 1 3
	jmp XctLc


; XctL8(LdrAddr,DataVec)

.XctL8:
	sta 3 1 2
	sta 0 2 2
	mov 1 3
	lda 0 .BR1
	sta 0 @ADREG
	lda 0 0 3
	com 0 0
	cycle 4
	sta 0 @OUTREG
	lda 0 .BR2
	sta 0 @ADREG
	lda 0 0 3
	cycle 12.
XctLb:	com 0 0
	sta 0 @OUTREG
	lda 0 2 2
	jmp xctm1

; XctL9(LdrAddr,DataVec)

.XctL9:
	sta 3 1 2
	sta 0 2 2
	mov 1 3
	lda 0 .BR1
	sta 0 @ADREG
	lda 0 0 3
	com 0 0
	cycle 5
	sta 0 @OUTREG
	lda 0 .BR2
	sta 0 @ADREG
	lda 0 0 3
	cycle 13.
	jmp XctLb

; Load procedures (cont'd)

; XctL12(LdrAddr,DataVec)

.XctL12:
	sta 3 1 2
	sta 0 2 2
	mov 1 3
	lda 0 .BR1
	sta 0 @ADREG
	lda 0 0 3
	coms 0 0
	sta 0 @OUTREG
	lda 0 .BR2
	sta 0 @ADREG
	lda 0 0 3
	jmp XctLb

; XctL18(LdrAddr,DataVec)

.XctL18:
	sta 3 1 2
	mov 1 3
	lda 1 .BR1
	sta 1 @ADREG
	lda 1 0 3
	lda 3 1 3
	comzr 1 1
	comr 3 3
	movzr 1 1
	movr 3 3
	movs 3 3
	sta 1 @OUTREG
	lda 1 .BR2
	sta 1 @ADREG
	sta 3 @OUTREG
xctm1a:	jmp xctm1

XctMica: jmp .XctMic


; XctL36(LdrAddr,DataVec)

.XctL36:
	sta 3 1 2
	mov 1 3
	lda 1 .BR0
	sta 1 @ADREG
	lda 1 0 3
	com 1 1
	sta 1 @OUTREG
	inc 3 3
XctLc:	lda 1 .BR1
	sta 1 @ADREG
	lda 1 0 3
	com 1 1
	sta 1 @OUTREG
	inc 3 3
XctLa:	lda 1 .BR2
	sta 1 @ADREG
	lda 1 0 3
	coms 1 1
	sta 1 @OUTREG
	jmp xctm1a

; Address memory routines used from ConvertAV
; They finish by either returning to 1 3 or jumping to RetMemX

; AdrRL()
; XctL8(LDX,lv(MADDRL lshift 8))

AdrRL:	movs 0 0
	sta 0 @TMP	; Use vector TMP to hold MADDRL lshift 8
	lda 0 .LDX
	LDA 1 TMP
	jmp .XctL8


; AdrIM() = XctL12(LDNPC,lv(MADDRL lshift 4)); XctMic(BRNIMA)

AdrIM:	cycle 4
	sta 0 @TMP
	lda 0 .LDNPC
	lda 1 TMP
	jsr .XctL12
	 2
	lda 0 .BRNIMA
	jsr XctMica
	 1
	jmp RetMemX


; AdrSM() = XctL9(LDY,lv(MADDRL lshift 7))

AdrDM:
AdrSM:	cycle 7
	sta 0 @TMP
	lda 0 .LDY
AdSMP:	lda 1 TMP
	jsr .XctL9
	 2
	jmp RetMemX


; AdrMP()
; XctL36(LDQ,CUM); XctMic(LDSMF)
; XctL9(((MADDRL & 1000B) ne 0 ? SETFLY,CLRFLY),MADDRL)
AdrMP:	lda 0 .LDQ
	lda 1 CUM
	jsr .XctL36
	 2
	lda 0 .LDSMF
	jsr XctMica		; SMFORF ← CUM
	 1
	lda 0 MADDRL
	cycle 7
	sta 0 @TMP		; TMP ← MADDRL for XctL9(LDY,TMP)
	lda 1 MADDRL
	lda 3 c1000
	lda 0 .CLRFLY
	and 1 3 szr
	lda 0 .SETFLY		; F[CUM] ← leading bit in MADDRL
	jmp AdSMP

; AdrMAIN()
; TMP!0 = (MADDRH lshift 12) + (MADDRL rshift 4)
; TMP!1 = MADDRL lshift 12

AdrMAIN:
	lda 0 MADDRH
	cycle 14
	lda 3 c170000
	and 0 3			; 1/ MADDRH lshift 12
	lda 0 MADDRL
	cycle 14
	sta 0 2 2
	lda 1 c7777
	and 1 0			; 0/ MADDRL rshift 4
	add 3 0
	lda 3 TMP
	sta 0 0 3
	lda 0 2 2
	lda 1 c170000
	and 1 0
	sta 0 1 3
	jmp RetMemX


; AdrLDR()
; LADDR = MADDRL*5 + LDRMEM

AdrLDR:
	lda 0 LDRMEM
	lda 1 MADDRL
	add 1 0
	addzl 1 1
	add 1 0
	sta 0 LADDR
	jmp 1 3


c170000:	170000
c7777:		7777
c3:		3
c1:		1
c20:		20
c1000:		1000
save3a:		0

.LDNPC:		LDNPC
.BRNIMA:	 BRNIMA
.LDX:		LDX
.LDSMF:		LDSMF
.CLRFLY:	CLRFLY
.SETFLY:	SETFLY
.SETFLQ:	SETFLQ
.CLRFLQ:	CLRFLQ
.LDY:		LDY
.LDQ:		LDQ
.LDEREG:	LDEREG

.IMA:		IMA
.NPC:		NPC
.X:		X
.Y:		Y

lvXctR36:	XctR36

; ConvertAV(AddrVec,MemX) = valof
; MADDRH = AddrVec!0; MADDRL = AddrVec!1
; test (MemX eq 6)
; ifso if MADDRH > MAINsize then resultis false
; ifnot if MADDRL ge table [ 4000B; 4000B; 4000B
;     1000B; 1000B; 2000B; 0B; 40B; 40B; 14B; LDRSIZ ] ! MemX
;     % (MADDRH ne 0) then resultis false
; switchon MemX into
; [
; case 0: case 1: case 2: AdrIM(); endcase
; case 3: AdrSM(); endcase
; case 10: case 11: case 4: AdrDM(); endcase
; case 5: AdrMP(); endcase
; case 6: AdrMAIN(); endcase
; case 7: case 8: AdrRL()
; case 9: endcase
; case 12: AdrLDR()
; case 13: endcase
; ]
; resultis MemX

CvAV4:	add 1 3
	lda 1 16 3	; Get memory size
	adcl# 0 1 szc	; Skip if AC1 gr AC0
	jmp BadAdr	; no good
	jsr 0 3		; ok, address it
	 0
RetMemX: lda 0 MemX	; resultis MemX
	lda 3 save3a
	jmp 1 3

; Have MemX ne 6 in 1
CvAV3:	lda 0 MADDRL
	jsr CvAV4

MAddr:	jmp AdrIM
	jmp AdrIM
	jmp AdrIM
	jmp AdrSM
	jmp AdrDM
	jmp AdrMP
	jmp BadAdr
	jmp AdrRL
	jmp AdrRL
	jmp RetMemX
	jmp AdrDM
	jmp AdrDM
	jmp AdrLDR
	jmp RetMemX

.MLen:	 10000		; IM[0,35]
	 10000		; IM[36,71]
	 10000		; IM[0,71]
	 1000		; SM
	 1000		; DM
	 2000		; MP
	    0		; MAIN (unused)
	   40		; RM
	   40		; LM
	   14		; STK
	 1000		; DM1
	 1000		; DM2
	LDRSIZE		; LDR
	   10		; KSTAT

.ConvertAV:
	sta 3 save3a
	sta 1 MemX
	mov 0 3		; 3←AddrVec
	lda 0 NMems	; Number of memories -1
	subl# 1 0 szc	; Skip if AC1 le AC0
	jmp BadAdr
	lda 0 1 3
	sta 0 MADDRL	; Low part of address
	lda 0 MainMemX
	sub# 1 0 szr	; Skip if MAIN address (else high part ignored)
	jmp CvAV3
	lda 0 0 3
	sta 0 MADDRH	; High part of address
	add# 0 0 snr	; Skip if high part non-0
	jmp AdrMAIN
	lda 3 MAINsize
	subl# 0 3 snc	; Skip if AC0 > AC3
	jmp AdrMAIN	; OK
BadAdr:	mkminusone 0 0	; return -1 if no good
	lda 3 save3a
	jmp 1 3

MemX:	0
MainMemX:	6
NMems:	15		; Number of memories -1

; Subroutine to restore registers clobbered incidentally during memory read/load
; RestoreMRegs(MemX)
;	switchon MemX into [
; case 0:
; case 1:
; case 2: XctL12(LDNPC,lv IMA); XctL12(BRNIMA,lv NPC); endcase
; case 3:
; case 4: case 10: case 11: XctL9(LDY,lv Y); XctL36(LDQ,Q); endcase
; case 5: XctL36(((F!1 & 20B) ne 0 ? SETFLQ,CLRFLQ),SMFORF)
;	   XctMic(LDSMF); XctL36(LDQ,Q); XctL9(LDY,lv Y); endcase
; case 7:
; case 8: XctL8(LDX,lv X); XctL36(LDQ,Q); endcase
; default: return
;	]
;	XctL36(LDEREG,EREG); @ADREG = 0; return

ResIM:	lda 0 .LDNPC
	lda 1 .IMA
	jsrii lvXctL12
	 2
	lda 0 .BRNIMA
	lda 1 .NPC
	jsrii lvXctL12
	 2
Resfx:	lda 0 .LDEREG
	lda 1 EREG
	jsrii lvXctL36
	 2
	mkzero 0 0
	sta 0 @ADREG
Resfin:	lda 3 save3a
	jmp 1 3	

ResMP:	lda 3 F
	lda 1 1 3
	lda 3 c20
	lda 0 .CLRFLQ
	and 3 1 szr		; CLEARF[CUM] if restoring CUM=0
	lda 0 .SETFLQ		; SETF[CUM] if restoring CUM=1
	lda 1 SMFORF
	jsrii lvXctL36
	 2
	lda 0 .LDSMF		; SMFORF ← Q
	jsrii lvXctMic
	 1

ResSM:
ResDM:	lda 0 .LDY		; Restore Y
	lda 1 .Y
	jsrii lvXctL9
	 2
	jmp ResSD

ResRL:	lda 0 .LDX
	lda 1 .X
	jsrii lvXctL8
	 2
ResSD:	lda 0 .LDQ
	lda 1 Q
	jsrii lvXctL36
	 2
	jmp Resfx

.RestoreMRegs:
	sta 3 save3a
	jsr ResMa

	jmp ResIM	;0 IM[0,35]
	jmp ResIM	;1 IM[36,71]
	jmp ResIM	;2 IM[0,71]
	jmp ResSM	;3 SM
	jmp ResDM	;4 DM
	jmp ResMP	;5 MP
	jmp Resfin	;6 MAIN
	jmp ResRL	;7 RM
	jmp ResRL	;8 LM
	jmp Resfin	;9 STK
	jmp ResDM	;10 DM1
	jmp ResDM	; 11 DM2
	jmp Resfin	;12 LDR
	jmp Resfin	;13 KSTAT

ResMa:	add 0 3
	jmp 0 3

lvXctL8: XctL8
lvXctL9: XctL9
lvXctL12: XctL12
lvXctL36: XctL36
lvXctMic: XctMic

; SetIMLd(DataVec)
; DataVec!0 = DataVec!0 xor 177760B
; let A = DataVec!2 lshift 4
; let B = DataVec!3 lcy 4
; let C = DataVec!4 lcy 4
; TMP!0 = A+(B & 17B)
; TMP!1 = (B & 177760B)+(C & 17B)
; TMP!2 = C & 177760B
.SetIMLd:
	sta 3 1 2
	sta 2 save2c
	mov 0 3		; AC3 = DataVec
	lda 2 TMP
	lda 0 4 3
	cycle 4		; DataVec!4 lcy 4
	lda 1 D177760
	and 0 1
	sta 1 2 2	; TMP!2 = DataVec!4 lshift 4
	lda 1 D17
	and 1 0
	sta 0 1 2	; TMP!1 = DataVec!4 rshift 12
	lda 0 3 3
	cycle 4		; DataVec!3 lcy 4
	lda 1 D177760
	and 0 1	
	sta 1 0 2	; TMP!0 = DataVec!3 lshift 4
	lda 1 D17
	and 1 0		; AC0 = DataVec!3 rshift 12
	lda 1 2 3
	movzl 1 1
	movzl 1 1
	movzl 1 1
	movzl 1 1	; DataVec!2 lshift 4
	add 0 1		; AC1 = (DataVec!2 lshift 4)+(DataVec!3 rshift 12)
	lda 0 0 2
	sta 1 0 2
	lda 1 1 2
	add 1 0
	sta 0 1 2	; TMP!1 = (DataVec!3 lshift 4)+(DataVec!4 rshift 12)
FixBA:	lda 0 0 3
	lda 1 D177760
	mov 0 2		; DataVec!0
	andzl 1 2
	add 1 0
	sub 2 0
	sta 0 0 3	; DataVec!0 = DataVec!0 xor 177760B
	lda 2 save2c
	lda 3 1 2
	jmp 1 3

save2c:	0
D17:	17
D177760: 177760
D7777:	7777
D170000: 170000
DX1:	0

; SetIMRd(DataVec)
; DataVec!0 = DataVec!0 xor 177760B
; let A = TMP!0 lcy 12
; let B = TMP!1 lcy 12
; let C = TMP!2 rshift 4
; DataVec!2 = DataVec!2 + (A & 7777B)
; DataVec!3 = (A & 170000B)+(B & 7777B)
; DataVec!4 = (B & 170000B)+C
.SetIMRd:
	sta 3 1 2
	sta 2 save2c
	mov 0 3		; AC3 = DataVec
	lda 2 TMP
	lda 0 0 2
	cycle 14
	sta 0 DX1	; DX1 = TMP!0 lcy 12
	lda 0 1 2
	cycle 14	; AC0 = TMP!1 lcy 12
	lda 2 2 2
	movzr 2 2
	movzr 2 2
	movzr 2 2
	movzr 2 2	; AC2 = TMP!2 rshift 4
	lda 1 D170000
	and 0 1		; AC1 = TMP!1 lshift 12
	add 1 2
	sta 2 4 3	; DataVec!4 = (TMP!1 lshift 12)+(TMP!2 rshift 4)
	lda 1 D7777
	and 1 0		; AC0 = TMP!1 rshift 4
	lda 1 DX1
	lda 2 D170000
	and 1 2		; AC2 = TMP!0 lshift 12
	add 2 0
	sta 0 3 3	; DataVec!3 = (TMP!0 lshift 12)+(TMP!1 rshift 4)
	lda 0 2 3
	lda 2 D7777
	and 2 1
	add 0 1
	sta 1 2 3	; DataVec!2 = (TMP!0 rshift 4)+DataVec!2
	jmp FixBA

mfetch = 66000
mstore = 66001
mrmw = 66002
mblks = 66003
mfblk32 = 66004
msblk32 = 66005
mfblk40 = 66006
msblk40 = 66007

; ZeroCore(AddrVec,Count) zeroes Maxc memory

.ZeroCore:
	sta 3 1 2	; Save return
	sta 1 2 2	; Save word count
	jsr .+4		; 3←DataVec (all zeroes)
	0
	0
	0
	mov 3 1		; 1←DataVec
	lda 3 2 2	; 3←Word count
	mblks		; Block transfer < 32K words
	lda 3 1 2
	jmp 1 3		; Return result in 0


.end