; bfsml.a
; Last modified April 5, 1980  5:54 PM by Taft

; 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

; Min(a, b); Max(a, b) -- signed compares (a and b must differ by < 2↑15)
; Umin(a, b); Umax(a, b) -- unsigned compares

.srel
Min:	.Min
Max:	.Max
Umin:	.Umin
Umax:	.Umax
.ent Min, Max, Umin, Umax
.nrel

.Min:	sle 0 1
	 mov 1 0
	jmp 1 3

.Max:	sge 0 1
	 mov 1 0
	jmp 1 3

.Umin:	sleu 0 1
	 mov 1 0
	jmp 1 3

.Umax:	sgeu 0 1
	 mov 1 0
	jmp 1 3


;DoubleAdd(a,b) a←a+b (a and b are pointers to double precision #'s)

	.srel
DoubleAdd:	.DoubleAdd
	.ent DoubleAdd

	.nrel
.DoubleAdd:
	sta 3 savedPC,2
	sta 1 temp,2	;=> first word of arg 2
	mov 1,3
	lda 1,1,3		;word 2 of arg 2
	mov 0 3
	lda 0,1,3		;word 2 of arg 1
	addz 1,0		;Sets carry if overflow
	sta 0,1,3		;Save word 2 of result
	lda 0,0,3		;word 1 of arg 1
	lda 1 @temp,2	;word 1 of arg 2
	mov 0,0,szc
	 inc 1,1
	add 1,0
	sta 0,0,3		;Save word 1 of result
	lda 3 savedPC,2
	jmp 1,3


; StartIO(ac0) - access to the SIO instruction

.srel
StartIO: .StartIO
.ent StartIO
.nrel

.StartIO: sio
	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
GotoLabel: .GotoLabel
	.bext CoCall,CallFrame,GotoFrame,CoReturn,ReturnTo,GotoLabel

	.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

; GotoLabel(frame, label, v) sends control to the specified label in the
; specified frame, and passes v in AC0
.GotoLabel: mov 0 3
	lda 0 extraArguments,2
	mov 3 2
	mov 1 3
	jmp 0,3



	.end