	.library	/sys$library:lib.mlb/
	.link	/sys$system:sys.stb/
	$secdef
	$pcbdef
	$phddef
	$prdef

	.macro	check	?l
	blbs	r0,l
	$exit_s	r0
l:
	.endm	check

	.macro	get_and_conv	in,pmt,out
	pushal	in
	pushal	pmt
	pushal	in
	calls	#3,g^lib$get_input
	check
	pushal	out
	pushal	in
	calls	#2,g^ots$cvt_tz_l
	check
	.endm	get_and_conv

	.macro	put	form,x1=#0,x2=#0,x3=#0,x4=#0,x5=#0
	$fao_s	ctrstr=fmt'form,outlen=buffer,outbuf=buffer,-
		p1=x1,p2=x2,p3=x3,p4=x4,p5=x5
	check
	pushal	buffer
	calls	#1,g^lib$put_output
	pushal	skip
	calls	#1,g^lib$put_output
	movl	#80,buffer
	.endm	put

	.macro	fetch	pfnloc,?label
	$crmpsc_s	inadr=pfnmap,flags=#<sec$m_pfnmap>,pagcnt=#1,-
			vbn=pfnloc
	blbs	r0,label
	ret
label:
	.endm	fetch

addr_200:
	.long	^x42
old_pri:
	.long	0
prompt:	.ascid	/Enter a virtual address:/
pid_prompt:
	.ascid	/Enter a pid (0 for your own):/
addr_asc:
	.long	8
	.address	10$
10$:	.blkb	8
addr:	.blkl	1
pid_asc:
	.long	8
	.address	10$
10$:	.blkb	8
pid:	.blkl	1
table:	.blkl	1
phd_args:
	.long	3
	.address	pid
	.address	phd
	.address	pcb
phd:	.blkl	1
pcb:	.blkl	1
	

	.entry	address_translation,^m<r6>
	get_and_conv	in=addr_asc,pmt=prompt,out=addr
	get_and_conv	in=pid_asc,pmt=pid_prompt,out=pid
	$setpri_s	pri=#31,prvpri=old_pri
	check
	extzv	#30,#2,addr,table
	casew	table,#0,#2
cbase:	.word	p0-cbase
	.word	p0-cbase
	.word	s0-cbase
p0:	$cmkrnl_s	routin=get_phd,arglst=phd_args
	check
	pushl	table
	pushl	phd
	pushl	addr
	calls	#3,g^p0_trans
	pushl	pid
	pushl	pcb
	calls	#2,g^cleanup_pcb
	brw	cleanup
s0:	pushl	addr
	calls	#1,g^s0_trans
cleanup:
	$setpri_s	pri=old_pri
	ret

pfnmap:
	.address	pfn
	.address	pfn+511
	.psect	data	page
	.align	page
pfn:	.blkl	512
	.psect	data_w	wrt
va:	.blkl	1
vpn:	.blkl	1
bwp:	.blkl	1
svapte:	.blkl	1
pte_vpn:
	.blkl	1
pte_bwp:
	.blkl	1
sbr:	.blkl	1
p0br:	.blkl	1
p0lr:	.blkl	1
pte_pfn:
	.blkl	1
va_pfn:	.blkl	1
pte_phy:.blkl	1
va_phy:	.blkl	1
va_contents:
	.blkl	1
pte_contents:
	.blkl	1
pa_of_spte:
	.blkl	1
pfn_of_spte:	.blkl	1
bwp_of_spte:	.blkl	1
contents_of_spte:
	.blkl	1
p1br:	.blkl	1
p1lr:	.blkl	1
buffer:	.long	80
	.address	10$
10$:	.blkb	80
fmt1:	.ascid	$Virtual address: !8XL!/ Page Table: !1XL VPN: !6XL BWP: !3XL$
fmt2:	.ascid	$P!1XLBR: !8XL VA of PTE = P0BR+4*VPN = !8XL$
fmt3:	.ascid	$PTE Virtual address: !8XL Page Table: 2  VPN: !6XL BWP: !3XL$
fmt4:	.ascid	$SBR: !8XL !/ PA of SPTE mapping PTE = SBR+4*VPN of PTE = !8XL$
fmt4a:	.ascid	$Phy addr of SPTE: !8XL  Contents of spte: !8XL$
fmt4b:	.ascid	$PFN of pte: !6XL$
fmt5:	.ascid	$Phys addr of PTE: !8XL  Contents of pte: !8XL$
fmt5a:	.ascid	$PFN of va: !6XL$
fmt6:	.ascid	$Physical address of VA: !8XL  Contents of VA: !8XL$
skip:	.ascid	/ /

	.entry	p0_trans,^m<r6,r7,r8,r9,r10>
	$cmkrnl_s	routin=do_p0_trans,arglst=(ap)
	check
	
	put 	form=1,x1=va,x2=12(ap),x3=vpn,x4=bwp
	tstl	12(ap)
	bneq	p1fmt
	put 	form=2,x1=12(ap),x2=p0br,x3=svapte
	brb	next_fmt
p1fmt:	put 	form=2,x1=12(ap),x2=p1br,x3=svapte
next_fmt:
	put 	form=3,x1=svapte,x2=pte_vpn,x3=pte_bwp
	put 	form=4,x1=sbr,x2=pa_of_spte
	put 	form=4a,x1=pa_of_spte,x2=contents_of_spte
	put 	form=4b,x1=pte_pfn
	put 	form=5,x1=pte_phy,x2=pte_contents
	put 	form=5a,x1=va_pfn
	put 	form=6,x1=va_phy,x2=va_contents
	ret		


	.entry	do_p0_trans,^m<r6,r7,r8,r9,r10>
	movl	4(ap),r6
	movl	8(ap),r7
	movl	12(ap),r10
	movl	r6,va
	extzv	#9,#21,r6,vpn
	extzv	#0,#9,r6,bwp
	tstl	table
	bneq	p1_regs
	movl	phd$l_p0br(r7),p0br
	movl	p0br,r10
	extzv	#0,#21,phd$l_p0lrastl(r7),p0lr
	cmpl	p0lr,vpn
	bgtru	ok
	movl	#ss$_accvio,r0
	ret
p1_regs:
	movl	phd$l_p1br(r7),p1br
	movl	p1br,r10
	extzv	#0,#21,phd$l_p1lr(r7),p1lr
	cmpl	p1lr,vpn
	blssu	ok
	movl	#ss$_accvio,r0
	ret
ok:
	ashl	#2,vpn,r8
	addl3	r10,r8,svapte
	extzv	#9,#21,svapte,pte_vpn
	extzv	#0,#9,svapte,pte_bwp
	ashl	#2,pte_vpn,r8
	mfpr	#pr$_sbr,r9
	movl	r9,sbr
	addl3	r9,r8,pa_of_spte
	extzv	#9,#21,pa_of_spte,pfn_of_spte
	extzv	#0,#9,pa_of_spte,bwp_of_spte
	fetch	pfn_of_spte
	movl	bwp_of_spte,r9
	movl	pfn(r9),contents_of_spte
	bbs	#31,contents_of_spte,valid1
	brw	return_now
valid1:	extzv	#0,#21,contents_of_spte,pte_pfn
	insv	pte_pfn,#9,#21,pte_phy
	insv	pte_bwp,#0,#9,pte_phy
	fetch	pte_pfn
	movl	pte_bwp,r9
	movl	pfn(r9),pte_contents
	bbs	#31,pte_contents,valid2
	brw	return_now
valid2:	extzv	#0,#21,pte_contents,va_pfn
	insv	va_pfn,#9,#21,va_phy
	insv	bwp,#0,#9,va_phy
	fetch	va_pfn
	movl	bwp,r9
	movl	pfn(r9),va_contents
	
return_now:
	movl	#ss$_normal,r0
	ret


	.entry	s0_trans,^m<r6,r7,r8,r9,r10>
	$cmkrnl_s	routin=do_s0_trans,arglst=(ap)
	check
	put	form=1,x1=va,x2=#2,x3=vpn,x4=bwp
	put	form=4,x1=sbr,x2=pa_of_spte
	put	form=4a,x1=pa_of_spte,x2=contents_of_spte
	put	form=5a,x1=va_pfn
	put	form=6,x1=va_phy,x2=va_contents
	ret

	.entry	do_s0_trans,^m<r6,r7,r8,r9,r10>
	movl	4(ap),r6
	movl	r6,va
	extzv	#9,#21,r6,vpn
	extzv	#0,#9,r6,bwp
	mfpr	#pr$_slr,r10
	cmpl	r10,vpn
	bgtru	s0_ok
	brw	s0_return_now
s0_ok:
	ashl	#2,vpn,r8
	mfpr	#pr$_sbr,r9
	movl	r9,sbr
	addl3	r9,r8,pa_of_spte
	extzv	#9,#21,pa_of_spte,pfn_of_spte
	extzv	#0,#9,pa_of_spte,bwp_of_spte
	fetch	pfn_of_spte
	movl	bwp_of_spte,r9
	movl	pfn(r9),contents_of_spte
	bbs	#31,contents_of_spte,s0_valid1
	brw	return_now
s0_valid1:
	extzv	#0,#21,contents_of_spte,va_pfn
	insv	va_pfn,#9,#21,va_phy
	insv	bwp,#0,#9,va_phy
	fetch	va_pfn
	movl	bwp,r9
	movl	pfn(r9),va_contents
s0_return_now:
	movl	#ss$_normal,r0
	ret

already_set:
	.blkl	1
	.entry	get_phd,^m<r5,r6,r7>
	movl	@4(ap),r5
	bneq	other
continue:
	movl	r4,@12(ap)
	bbc	#pcb$v_phdres,pcb$l_sts(r4),err_ret
	clrl	already_set
	bbcs	#pcb$v_pswapm,pcb$l_sts(r4),is_clear
	incl	already_set
is_clear:
	movl	pcb$l_phd(r4),@8(ap)
	movl	#ss$_normal,r0	
	ret
other:	movl	r5,r0
	jsb	g^exe$epid_to_pcb
	tstl	r0
	beql	err_ret
	movl	r0,r4
	brw	continue
err_ret:movl	#ss$_nonexpr,r0
	ret

	.entry	cleanup_pcb,^m<r4>
	$cmkrnl_s	routin=clean_in_kernel,arglst=(ap)
	check
	ret
	.entry	clean_in_kernel,^m<r4>
	movl	4(ap),r4
	cmpl	pcb$l_epid(r4),8(ap)
	bneq	he_is_history
	tstl	already_set
	bneq	done
	bicl	#pcb$m_pswapm,pcb$l_sts(r4)
done:
he_is_history:
	movl	#ss$_normal,r0
	ret
	.end	address_translation
