; miscellaneous machine code

; frame
	callersFrame=0
	savedPC=1
	temp=2
	extraArguments=3

; machine code for messing with frames

	.srel
FrameSize: pFrameSize
MyFrame: pMyFrame
CallersFrame: pCallersFrame
	.bext FrameSize,MyFrame,CallersFrame

	.nrel

pFrameSize: mov 3 1
	mov 0 3
	lda 0 2,3
	mov 1 3
	jmp 1,3

pMyFrame: mov 2 0
	jmp 1,3

pCallersFrame: lda 0 callersFrame,2
	jmp 1,3


; machine code for getting at block store and transfer 
; instructions
	.srel
MoveBlock: pMoveBlock
SetBlock: pSetBlock
Zero:	pZero
	.bext MoveBlock,SetBlock,Zero

	.nrel

pMoveBlock: sta 3 savedPC,2
	mkone 3 3
	sub 3 1
	sub 0 3
	mov 1 0
	neg 3 1
	lda 3 extraArguments,2
	add 3 1
	neg 3 3
	blt
	lda 3 savedPC,2
	jmp 1,3

pZero:	sta 1 extraArguments,2
	mkzero 1 1
; fall through

pSetBlock: sta 3 savedPC,2
	mkone 3 3
	sub 0 3
	mov 1 0
	neg 3 1
	lda 3 extraArguments,2
	add 3 1
	neg 3 3
	blks
	lda 3 savedPC,2
	jmp 1,3


; machine code for unsigned compare.  Returns -1 is ac0 ls ac1,
; 0 if ac0 eq ac1, and 1 if ac2 gr ac1, taken as 16 bit positive
; numbers
	.srel
Usc:	pUsc
	.bext Usc

	.nrel
pUsc:	adcz# 0 1 szc
	jmp Uscr1
	subz 1 0 szr
	mkone 0 0
	jmp 1,3
Uscr1:	mknil 0 0
	jmp 1,3


; table to convert from bit number to bit position
	.srel
oneBits: .oneBits
	.bext oneBits

	.nrel
.oneBits: 100000
	40000
	20000
	10000
	4000
	2000
	1000
	400
	200
	100
	40
	20
	10
	4
	2
	1

; free page fileId
	.srel
freePageId: .freePageId
	.bext freePageId

	.nrel
.freePageId: -1
	-1
	-1


; machine code for simple coroutine linkages
	.srel
CallFrame: .CallFrame
GotoFrame: .GotoFrame
CoCall:	.CoCall
CoReturn: .CoReturn
ReturnTo: .ReturnTo
	.bext CoCall,CallFrame,GotoFrame,CoReturn,ReturnTo

	.nrel
; CallFrame(dest frame[, arg 1[, arg 2]]) sends control to
; the specified frame and links it back to this one
.CallFrame: sta 3 savedPC,2
	mov 0 3
	sta 2 callersFrame,3
callf1:	mov 1 0
	lda 1 extraArguments,2
callf2:	mov 3 2
	lda 3 savedPC,2
	jmp 1,2

; just like CallFrame, but doesn't plant the return link.  This
; is like Mesa's transfer
.GotoFrame: sta 3 savedPC,2
	mov 0 3
	jmp callf1

; CoCall(a, b)=CallFrame(MyFrame()>>F.callersFrame, a, b)
.CoCall: sta 3 savedPC,2
	lda 3 callersFrame,2
	sta 2 callersFrame,3
	jmp callf2

; just like CoCall, but doesn't plant the return link
.CoReturn: sta 3 savedPC,2
	lda 2 callersFrame,2
	lda 3 savedPC,2
	jmp 1,3

; ReturnTo(label) does a return to the specified label
.ReturnTo: lda 2 callersFrame,2
	mov 0 3
	jmp 0,3



	.srel
DisableInterrupts: .DisableInterrupts
EnableInterrupts: .EnableInterrupts
	.bext DisableInterrupts, EnableInterrupts

	.nrel


;DisableInterrupts - No interrupts take until enabled
.DisableInterrupts: dir
	jmp 1,3

;EnableInterrupts - Let interrupts take
.EnableInterrupts: eir
	jmp 1,3

	.end