4.3BSD-Reno/src/sys/GENERIC.allvax/locore.c

Compare this file to the similar file:
Show the results in this format:

#define	P_LINK 0
#define	P_RLINK 4
#define	P_XLINK 116
#define	P_ADDR 16
#define	P_PRI 21
#define	P_STAT 23
#define	P_WCHAN 104
#define	P_TSIZE 72
#define	P_DSIZE 76
#define	P_SSIZE 84
#define	P_P0BR 112
#define	P_SZPT 70
#define	P_TEXTP 108
#define	P_FLAG 44
#define	SSLEEP 1
#define	SRUN 3
#define	UBA_BRRVR 48
#define	UH_UBA 4
#define	UH_VEC 28
#define	UH_SIZE 84
#define	RP_FLAG 12
#define	X_CADDR 64
#define	V_SWTCH 0
#define	V_TRAP 4
#define	V_SYSCALL 8
#define	V_INTR 12
#define	V_SOFT 16
#define	V_PDMA 20
#define	V_FAULTS 92
#define	V_PGREC 52
#define	V_FASTPGREC 112
#define	UPAGES 16
#define	CLSIZE 2
#define	MAXPHYS 64512
#define	SYSPTSIZE 3584
#define	USRPTSIZE 4096
#define	MSGBUFPTECNT 8
#define	MCLBYTES 1024
#define	NMBCLUSTERS 256
#define	NKMEMCLUSTERS 512
#define	U_PROCP 128
#define	U_RU 1472
#define	RU_MINFLT 32
#define	SZ_CMAP 20
/*
 * Copyright (c) 1982, 1986 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 *
 *	@(#)rpb.s	7.1 (Berkeley) 6/5/86
 */

/*
 * This has to get loaded first (physical 0) as 780 memory restart rom
 * only looks for rpb on a 64K page boundary (doc isn't wrong,
 * it never says what size "page boundary" rpb has to be on).
 */
	.globl	_rpb
_rpb:
	.space	508
erpb:
	.space	4
/*
 * Copyright (c) 1982, 1986 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 *
 *	@(#)scb.s	7.4 (Berkeley) 5/14/88
 */

#include "uba.h"

/*
 * System control block
 */
	.set	INTSTK,1	# handle this interrupt on the interrupt stack
	.set	HALT,3		# halt if this interrupt occurs

_scb:	.globl	_scb

#define	KS(a)	.long	_X/**/a
#define	IS(a)	.long	_X/**/a+INTSTK
#define	STOP(a)	.long	_X/**/a+HALT

#define	STRAY(x)	.long	_scbstray+2*(x)+INTSTK
#define	STRAY3(n)	STRAY(n);STRAY(n+4);STRAY(n+8)
#define	STRAY4(n)	STRAY3(n);STRAY(n+12)
#define	STRAY15(n)	STRAY4(n);STRAY4(n+16);STRAY4(n+32);STRAY3(n+48)
#define	STRAY16(n)	STRAY15(n);STRAY(n+60)
#define	NEX0(n)	IS(nex0zvec);STRAY15(n+4)
#define	NEX1(n)	IS(nex1zvec);STRAY15(n+4)

/* 000 */	IS(passiverel);	IS(machcheck);	IS(kspnotval);	STOP(powfail);
/* 010 */	KS(privinflt);	KS(xfcflt);	KS(resopflt);	KS(resadflt);
/* 020 */	KS(protflt);	KS(transflt);	KS(tracep);	KS(bptflt);
/* 030 */	KS(compatflt);	KS(arithtrap);	STRAY(0x38);	STRAY(0x3c);
/* 040 */	KS(syscall);	KS(chme);	KS(chms);	KS(chmu);
/* 050 */	IS(sbisilo);	IS(cmrd);	IS(sbi0alert);	IS(sbi0fault);
/* 060 */	IS(wtime);	IS(sbi0fail);	STRAY(0x68);	STRAY(0x6c);
/* 070 */	STRAY(0x70);	STRAY(0x74);	STRAY(0x78);	STRAY(0x7c);
/* 080 */	STRAY(0x80);	STRAY(0x84);	KS(astflt);	STRAY(0x8c);
/* 090 */	STRAY(0x90);	STRAY(0x94);	STRAY(0x98);	STRAY(0x9c);
/* 0a0 */	IS(softclock);	STRAY(0xa4);	STRAY(0xa8);	STRAY(0xac);
/* 0b0 */	IS(netintr);	STRAY(0xb4);	STRAY(0xb8);	IS(kdbintr);
/* 0c0 */	IS(hardclock);	STRAY(0xc4);	KS(emulate);	KS(emulateFPD);
/* 0d0 */	STRAY(0xd0);	STRAY(0xd4);	STRAY(0xd8);	STRAY(0xdc);
/* 0e0 */	STRAY(0xe0);	STRAY(0xe4);	STRAY(0xe8);	STRAY(0xec);
/* 0f0 */	IS(consdin);	IS(consdout);	IS(cnrint);	IS(cnxint);
/* 100 */	NEX0(0x100);		/* ipl 0x14, nexus 0-15 */
/* 140 */	NEX0(0x140);		/* ipl 0x15, nexus 0-15 */
/* 180 */	NEX0(0x180);		/* ipl 0x16, nexus 0-15 */
/* 1c0 */	NEX0(0x1c0);		/* ipl 0x17, nexus 0-15 */

/*
 * 750 hardware reads through UNIvec (scb + 512 bytes) to find Unibus
 * interrupt vectors.  780s use this space as a jump table (lookup
 * code in locore.s makes 780s work like 750s).  Additional pages
 * of interrupt vectors for additional UBAs follow immediately.
 *
 * 8600s may use the next page as a second SCB, for which purpose we init
 * it here.  Everything else will simply replace these with Unibus vectors.
 * An additional page is provided for UBA jump tables if the second
 * scb might be present.  Other CPUs with additional scbs should expand
 * this area as needed.
 */
	.globl	_UNIvec
	.globl	_eUNIvec
_UNIvec:
#if VAX8600
/* 200 */	STRAY16(0x200);		/* unused (?) */
/* 240 */	STRAY16(0x240);		/* sbi1fail etc. set at boot time */
/* 280 */	STRAY16(0x280);		/* unused (?) */
/* 2c0 */	STRAY16(0x2c0);		/* unused (?) */
/* 300 */	NEX1(0x300);		/* ipl 0x14, nexus 0-15, sbia 1 */
/* 340 */	NEX1(0x340);		/* ipl 0x15, nexus 0-15, sbia 1 */
/* 380 */	NEX1(0x380);		/* ipl 0x16, nexus 0-15, sbia 1 */
/* 3c0 */	NEX1(0x3c0);		/* ipl 0x17, nexus 0-15, sbia 1 */

#endif
#if NUBA > 0
		.space	512*NUBA	# 750 first/second unibus intr vector
					# UBA jump tables on 780's
#endif
_eUNIvec:
#define	I_CLOCK	0
#define	I_CNR	4
#define	I_CNX	8
#define	I_TUR	12
#define	I_TUX	16
#define	I_MBA0	20
#define	I_MBA1	24
#define	I_MBA2	28
#define	I_MBA3	32
#define	I_UBA0	36
#define	I_UBA1	40
#define	I_UBA2	44
#define	I_UBA3	48
/*
 * Copyright (c) 1980, 1986 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 *
 *	@(#)locore.s	7.24 (Berkeley) 5/10/90
 */

#include "psl.h"
#include "pte.h"

#include "errno.h"
#include "syscall.h"
#include "cmap.h"

#include "mtpr.h"
#include "trap.h"
#include "cpu.h"
#include "nexus.h"
#include "cons.h"
#include "clock.h"
#include "ioa.h"
#include "ka630.h"
#include "ka650.h"
#include "ka820.h"
#include "../vaxuba/ubareg.h"

#include "dz.h"
#include "uu.h"
#include "ps.h"
#include "mba.h"
#include "uba.h"

	.set	HIGH,0x1f	# mask for total disable
	.set	MCKVEC,4	# offset into scb of machine check vector
	.set	NBPG,512
	.set	PGSHIFT,9
	.set	SYSTEM,0x80000000	# virtual address of system start

	.set	NISP,3		# number of interrupt stack pages

/*
 * User structure is UPAGES at top of user space.
 */
	.globl	_u
	.set	_u,0x80000000 - UPAGES*NBPG

	.globl	_intstack
_intstack:
	.space	NISP*NBPG
eintstack:

/*
 * Do a dump.
 * Called by auto-restart.
 * May be called manually.
 */
	.align	2
	.globl	_doadump
	.globl	_msgbufmapped
_doadump:
	nop; nop				# .word 0x0101
#define	_rpbmap	_Sysmap				# rpb, scb, UNIvec[], istack*4
	bicl2	$PG_PROT,_rpbmap
	bisl2	$PG_KW,_rpbmap
	mtpr	$0,$TBIA
	tstl	_rpb+RP_FLAG			# dump only once!
	bneq	1f
	incl	_rpb+RP_FLAG
	movl	sp,erpb
	movab	erpb,sp
	mfpr	$PCBB,-(sp)
	mfpr	$MAPEN,-(sp)
	mfpr	$IPL,-(sp)
	clrl	_msgbufmapped
	mtpr	$0,$MAPEN
	mtpr	$HIGH,$IPL
	pushr	$0x3fff
	calls	$0,_dumpsys
1:
	clrl	r11				# boot flags
	calls	$0,_vaxboot
	halt

/*
 * Interrupt vector routines
 */ 
	.globl	_waittime

#define	SCBVEC(name)	.align 2; .globl _X/**/name; _X/**/name
#define	PANIC(msg)	clrl _waittime; pushab 1f; \
			calls $1,_panic; 1: .asciz msg
#define	PRINTF(n,msg)	pushab 1f; calls $n+1,_printf; MSG(msg)
#define	MSG(msg)	.data; 1: .asciz msg; .text
#define	PUSHR		pushr $0x3f
#define	POPR		popr $0x3f

	.data
nofault: .long	0	# where to go on predicted machcheck
	.text
SCBVEC(machcheck):
	tstl	nofault
	bneq	1f
	PUSHR; pushab 6*4(sp); calls $1,_machinecheck; POPR;
	addl2 (sp)+,sp; rei
	.align	2
1:
	casel	_cpu,$1,$VAX_MAX
0:
	.word	8f-0b		# 1 is 780
	.word	5f-0b		# 2 is 750
	.word	5f-0b		# 3 is 730
	.word	7f-0b		# 4 is 8600
	.word	5f-0b		# 5 is 8200
	.word	1f-0b		# 6 is 8800 (unsupported)
	.word	1f-0b		# 7 is 610  (unsupported)
	.word	1f-0b		# 8 is 630
	.word	1f-0b		# 9 is ???
	.word	9f-0b		# 10 is 650
5:
#if defined(VAX8200) || defined(VAX750) || defined(VAX730)
	mtpr	$0xf,$MCESR
#endif
	brb	1f
7:
#if VAX8600
	mtpr	$0,$EHSR
#endif
	brb	1f
8:
#if VAX780
	mtpr	$0,$SBIFS
#endif
	brb	1f
9:
#if VAX650
	bitl	$PG_V,_KA650MERRmap
	beql	1f	# don't bother clearing err reg if not mapped in
	movl	$DSER_CLEAR,_ka650merr+4
#endif
1:
	addl2	(sp)+,sp		# discard mchchk trash
	movl	nofault,(sp)
	rei

SCBVEC(kspnotval):
	PANIC("KSP not valid");
SCBVEC(powfail):
	halt
SCBVEC(chme): SCBVEC(chms): SCBVEC(chmu):
	PANIC("CHM? in kernel");

SCBVEC(nex0zvec):
	PUSHR
	clrl	r0
	brb	1f
SCBVEC(nex1zvec):
	PUSHR
	movl	$1,r0
1:
	cmpl	_cpu,$VAX_8600		# this is a frill
	beql	2f
	mfpr	$IPL,-(sp)
	PRINTF(1, "nexus stray intr ipl%x\n")
	POPR
	rei
2:
	pushl	r0
	mfpr	$IPL,-(sp)
	PRINTF(2, "nexus stray intr ipl%x sbia%d\n")
	POPR
	rei

SCBVEC(cmrd):
	PUSHR; calls $0,_memerr; POPR; rei

SCBVEC(wtime):			/* sbi0err on 8600 */
#if VAX8600
	cmpl	_cpu,$VAX_8600
	bneq	wtimo
	PANIC("sbia0 error")
wtimo:
#endif
	PUSHR; pushl 6*4(sp); PRINTF(1, "write timeout %x\n"); POPR
	PANIC("wtimo")

SCBVEC(sbi0fail):
	PANIC("sbia0 fail")
SCBVEC(sbi0alert):
#if VAX8200
	cmpl	_cpu,$VAX_8200
	bneq	alert
	PUSHR; calls $0,_rxcdintr; POPR; rei
alert:
#endif
	PANIC("sbia0 alert")
SCBVEC(sbi0fault):
	PANIC("sbia0 fault")

#ifdef notyet
#if VAX8600
SCBVEC(sbi1fail):
	PANIC("sbia1 fail")
SCBVEC(sbi1alert):
	PANIC("sbia1 alert")
SCBVEC(sbi1fault):
	PANIC("sbia1 fault")
SCBVEC(sbi1err):
	PANIC("sbia1 error")
#endif
#endif

/*
 * BI 0 bus error (8200), or SBI silo compare error (others)
 * VMS boot leaves us 1 BI error to ignore.
 */
#if VAX8200 && 0
	.data
	.align	2
_ignorebi: .globl _ignorebi
	.long	1
	.text
#endif VAX8200

SCBVEC(sbisilo):
#if VAX8200
	cmpl	_cpu,$VAX_8200
	bneq	sbisilo
#if 0
	blbs	_ignorebi,1f
#else
	blbs	_cold,1f
#endif
	PUSHR; pushl $0; calls $1,_bi_buserr; POPR
1:
	rei
#endif
sbisilo:
	PANIC("sbi silo compare error")

/*
 * SCB stray interrupt catcher.  Compute and print the actual
 * SCB vector (for fault diagnosis).
 */
	.align	2
_scbstray: .globl _scbstray
#define	PJ	PUSHR;jsb 1f
	/* 128 of 'em */
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
#if VAX8600
	/* and another 128, for the second SBIA's scb */
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
#endif
#undef PJ
1:
	subl3	$_scbstray+8,(sp)+,r0
	mfpr	$IPL,-(sp)
	ashl	$-1,r0,-(sp)
/* call a C handler instead? perhaps later */
	PRINTF(2, "stray scb intr vec 0x%x ipl%x\n")
	POPR
	rei

#if NMBA > 0
SCBVEC(mba3int):
	PUSHR; incl _intrcnt+I_MBA3; pushl $3; brb 1f
SCBVEC(mba2int):
	PUSHR; incl _intrcnt+I_MBA2; pushl $2; brb 1f
SCBVEC(mba1int):
	PUSHR; incl _intrcnt+I_MBA1; pushl $1; brb 1f
SCBVEC(mba0int):
	PUSHR; incl _intrcnt+I_MBA0; pushl $0
1:	calls $1,_mbintr
	POPR
	incl	_cnt+V_INTR
	rei
#endif

#ifdef DW780
/*
 * Registers for the uba handling code
 */
#define	rUBANUM	r0
#define	rUBAHD	r1
#define	rUVEC	r3
#define	rUBA	r4
/* r2,r5 are scratch */

#define	I_UBA	I_UBA0		/* base of UBA interrupt counters */

#if NUBA > 4
SCBVEC(ua7int):
	PUSHR; movl $7,rUBANUM; moval _uba_hd+(7*UH_SIZE),rUBAHD; brb 1f
SCBVEC(ua6int):
	PUSHR; movl $6,rUBANUM; moval _uba_hd+(6*UH_SIZE),rUBAHD; brb 1f
SCBVEC(ua5int):
	PUSHR; movl $5,rUBANUM; moval _uba_hd+(5*UH_SIZE),rUBAHD; brb 1f
SCBVEC(ua4int):
	PUSHR; movl $4,rUBANUM; moval _uba_hd+(4*UH_SIZE),rUBAHD; brb 1f
#endif
SCBVEC(ua3int):
	PUSHR; movl $3,rUBANUM; moval _uba_hd+(3*UH_SIZE),rUBAHD; brb 1f
SCBVEC(ua2int):
	PUSHR; movl $2,rUBANUM; moval _uba_hd+(2*UH_SIZE),rUBAHD; brb 1f
SCBVEC(ua1int):
	PUSHR; movl $1,rUBANUM; moval _uba_hd+(1*UH_SIZE),rUBAHD; brb 1f
SCBVEC(ua0int):
	PUSHR; movl $0,rUBANUM; moval _uba_hd+(0*UH_SIZE),rUBAHD;
1:
	mfpr	$IPL,r2				/* r2 = mfpr(IPL); */
	movl	UH_UBA(rUBAHD),rUBA		/* uba = uhp->uh_uba; */
	movl	UBA_BRRVR-0x14*4(rUBA)[r2],rUVEC
					/* uvec = uba->uba_brrvr[r2-0x14] */
ubanorm:
	bleq	ubaerror 
	addl2	UH_VEC(rUBAHD),rUVEC		/* uvec += uh->uh_vec */
	bicl3	$3,(rUVEC),r1 
	jmp	2(r1)				/* 2 skips ``pushr $0x3f'' */
ubaerror:
	PUSHR; calls $0,_ubaerror; POPR		/* ubaerror r/w's r0-r5 */
	tstl rUVEC; jneq ubanorm		/* rUVEC contains result */
	incl _intrcnt+I_UBA[rUBANUM]
	incl	_cnt+V_INTR
	POPR
	rei
#endif
SCBVEC(cnrint):
	PUSHR; calls $0,_cnrint; POPR
	incl _cnt+V_INTR
	incl _intrcnt+I_CNR
	rei
SCBVEC(cnxint):
	PUSHR; calls $0,_cnxint; POPR
	incl _cnt+V_INTR
	incl _intrcnt+I_CNX
	rei
SCBVEC(hardclock):
	PUSHR
	mtpr $ICCS_RUN|ICCS_IE|ICCS_INT|ICCS_ERR,$ICCS
#if NPS > 0
	pushl	4+6*4(sp); pushl 4+6*4(sp);
	calls	$2,_psextsync
#endif
	pushl 4+6*4(sp); pushl 4+6*4(sp);
	calls $2,_hardclock			# hardclock(pc,psl)
	POPR;
	incl	_cnt+V_INTR
	incl	_intrcnt+I_CLOCK
	rei
SCBVEC(softclock):
	PUSHR
	pushl	4+6*4(sp); pushl 4+6*4(sp);
	calls	$2,_softclock			# softclock(pc,psl)
	POPR; 
	incl	_cnt+V_SOFT
	rei

#include "../net/netisr.h"
	.globl	_netisr
SCBVEC(netintr):
	PUSHR
#include "imp.h"
#if NIMP > 0
	bbcc	$NETISR_IMP,_netisr,1f; calls $0,_impintr; 1:
#endif
#ifdef INET
	bbcc	$NETISR_IP,_netisr,1f; calls $0,_ipintr; 1:
#endif
#ifdef NS
	bbcc	$NETISR_NS,_netisr,1f; calls $0,_nsintr; 1:
#endif
#ifdef ISO
	bbcc	$NETISR_ISO,_netisr,1f; calls $0,_clnlintr; 1:
#endif
	POPR
	incl	_cnt+V_SOFT
	rei

SCBVEC(consdin):
	PUSHR;
	incl	_intrcnt+I_TUR
	casel	_cpu,$VAX_750,$VAX_8200
0:
	.word	5f-0b		# 2 is VAX_750
	.word	3f-0b		# 3 is VAX_730
	.word	6f-0b		# 4 is VAX_8600
	.word	7f-0b		# 5 is VAX_8200
	halt
5:
#if defined(VAX750) && !defined(MRSP)
	jsb	tudma
#endif
3:
#if defined(VAX750) || defined(VAX730)
	calls	$0,_turintr
	brb	2f
#else
	halt
#endif
7:
#if VAX8200
	calls	$0,_rx50intr
	brb	2f
#else
	halt
#endif
6:
#if VAX8600
	calls	$0,_crlintr
#else
	halt
#endif
2:
	POPR
	incl	_cnt+V_INTR
	rei

#if defined(VAX750) || defined(VAX730)
SCBVEC(consdout):
	PUSHR; calls $0,_tuxintr; POPR
	incl _cnt+V_INTR
	incl _intrcnt+I_TUX
	rei
#else
SCBVEC(consdout):
	halt
#endif

#if NDZ > 0
/*
 * DZ pseudo dma routine:
 *	r0 - controller number
 */
	.align	1
	.globl	dzdma
dzdma:
	mull2	$8*20,r0
	movab	_dzpdma(r0),r3		# pdma structure base
					# for this controller
dzploop:
	movl	r3,r0	
	movl	(r0)+,r1		# device register address
	movzbl	1(r1),r2		# get line number
	bitb	$0x80,r2		# TRDY on?
	beql	dzprei			# no	
	bicb2	$0xf8,r2		# clear garbage bits
	mull2	$20,r2
	addl2	r2,r0			# point at line's pdma structure
	movl	(r0)+,r2		# p_mem
	cmpl	r2,(r0)+		# p_mem < p_end ?
	bgequ	dzpcall			# no, go call dzxint
	movb	(r2)+,6(r1)		# dztbuf = *p_mem++
	movl	r2,-8(r0)
	brb 	dzploop			# check for another line
dzprei:
	POPR
	incl	_cnt+V_PDMA
	rei

dzpcall:
	pushl	r3
	pushl	(r0)+			# push tty address
	calls	$1,*(r0)		# call interrupt rtn
	movl	(sp)+,r3
	brb 	dzploop			# check for another line
#endif

#if NUU > 0 && defined(UUDMA)
/*
 * Pseudo DMA routine for tu58 (on DL11)
 *	r0 - controller number
 */
	.align	1
	.globl	uudma
uudma:
	movl	_uudinfo[r0],r2
	movl	16(r2),r2		# r2 = uuaddr
	mull3	$48,r0,r3
	movab	_uu_softc(r3),r5	# r5 = uuc

	cvtwl	2(r2),r1		# c = uuaddr->rdb
	bbc	$15,r1,1f		# if (c & UUDB_ERROR)
	movl	$13,16(r5)		#	uuc->tu_state = TUC_RCVERR;
	rsb				#	let uurintr handle it
1:
	tstl	4(r5)			# if (uuc->tu_rcnt) {
	beql	1f
	movb	r1,*0(r5)		#	*uuc->tu_rbptr++ = r1
	incl	(r5)
	decl	4(r5)			#	if (--uuc->tu_rcnt)
	beql	2f			#		done
	tstl	(sp)+
	POPR				# 	registers saved in ubglue.s
	rei				# }
2:
	cmpl	16(r5),$8		# if (uuc->tu_state != TUS_GETH)
	beql	2f			# 	let uurintr handle it
1:
	rsb
2:
	mull2	$14,r0			# sizeof(uudata[ctlr]) = 14
	movab	_uudata(r0),r4		# data = &uudata[ctlr];
	cmpb	$1,(r4)			# if (data->pk_flag != TUF_DATA)
	bneq	1b
#ifdef notdef
	/* this is for command packets */
	beql	1f			# 	r0 = uuc->tu_rbptr
	movl	(r5),r0
	brb	2f
1:					# else
#endif
	movl	24(r5),r0		# 	r0 = uuc->tu_addr
2:
	movzbl	1(r4),r3		# counter to r3 (data->pk_count)
	movzwl	(r4),r1			# first word of checksum (=header)
	mfpr	$IPL,-(sp)		# s = spl5();
	mtpr	$0x15,$IPL		# to keep disk interrupts out
	clrw	(r2)			# disable receiver interrupts
3:	bbc	$7,(r2),3b		# while ((uuaddr->rcs & UUCS_READY)==0);
	cvtwb	2(r2),(r0)+		# *buffer = uuaddr->rdb & 0xff
	sobgtr	r3,1f			# continue with next byte ...
	addw2	2(r2),r1		# unless this was the last (odd count)
	brb	2f

1:	bbc	$7,(r2),1b		# while ((uuaddr->rcs & UUCS_READY)==0);
	cvtwb	2(r2),(r0)+		# *buffer = uuaddr->rdb & 0xff
	addw2	-2(r0),r1		# add to checksum..
2:
	adwc	$0,r1			# get the carry
	sobgtr	r3,3b			# loop while r3 > 0
/*
 * We're ready to get the checksum
 */
1:	bbc	$7,(r2),1b		# while ((uuaddr->rcs & UUCS_READY)==0);
	cvtwb	2(r2),12(r4)		# get first (lower) byte
1:	bbc	$7,(r2),1b
	cvtwb	2(r2),13(r4)		# ..and second
	cmpw	12(r4),r1		# is checksum ok?
	beql	1f
	movl	$14,16(r5)		# uuc->tu_state = TUS_CHKERR
	brb	2f			# exit
1:
	movl	$11,16(r5)		# uuc->tu_state = TUS_GET (ok)
2:
	movw	$0x40,(r2)		# enable receiver interrupts
	mtpr	(sp)+,$IPL		# splx(s);
	rsb				# continue processing in uurintr
#endif

#if defined(VAX750) && !defined(MRSP)
/*
 * Pseudo DMA routine for VAX-11/750 console tu58 
 *   	    (without MRSP)
 */
	.align	1
	.globl	tudma
tudma:
	movab	_tu,r5			# r5 = tu
	tstl	4(r5)			# if (tu.tu_rcnt) {
	beql	3f
	mfpr	$CSRD,r1		# get data from tu58
	movb	r1,*0(r5)		#	*tu.tu_rbptr++ = r1
	incl	(r5)
	decl	4(r5)			#	if (--tu.tu_rcnt)
	beql	1f			#		done
	tstl	(sp)+
	POPR				# 	registers saved in ubglue.s
	rei				# 	data handled, done
1:					# }
	cmpl	16(r5),$8		# if (tu.tu_state != TUS_GETH)
	beql	2f			# 	let turintr handle it
3:
	rsb
2:
	movab	_tudata,r4		# r4 = tudata
	cmpb	$1,(r4)			# if (tudata.pk_flag != TUF_DATA)
	bneq	3b			# 	let turintr handle it
1:					# else
	movl	24(r5),r1		# get buffer pointer to r1
	movzbl	1(r4),r3		# counter to r3
	movzwl	(r4),r0			# first word of checksum (=header)
	mtpr	$0,$CSRS		# disable receiver interrupts
3:
	bsbw	5f			# wait for next byte
	mfpr	$CSRD,r5
	movb	r5,(r1)+		# *buffer = rdb
	sobgtr	r3,1f			# continue with next byte ...
	mfpr	$CSRD,r2		# unless this was the last (odd count)
	brb	2f

1:	bsbw	5f			# wait for next byte
	mfpr	$CSRD,r5
	movb	r5,(r1)+		# *buffer = rdb
	movzwl	-2(r1),r2		# get the last word back from memory
2:
	addw2	r2,r0			# add to checksum..
	adwc	$0,r0			# get the carry
	sobgtr	r3,3b			# loop while r3 > 0
/*
 * We're ready to get the checksum.
 */
	bsbw	5f
	movab	_tudata,r4
	mfpr	$CSRD,r5
	movb	r5,12(r4)		# get first (lower) byte
	bsbw	5f
	mfpr	$CSRD,r5
	movb	r5,13(r4)		# ..and second
	movab	_tu,r5
	cmpw	12(r4),r0		# is checksum ok?
	beql	1f
	movl	$14,16(r5)		# tu.tu_state = TUS_CHKERR
	brb	2f			# exit
1:
	movl	$11,16(r5)		# tu.tu_state = TUS_GET
2:
	mtpr	$0x40,$CSRS		# enable receiver interrupts
	rsb				# continue processing in turintr
/*
 * Loop until a new byte is ready from
 * the tu58, make sure we don't loop forever
 */
5:
	movl	$5000,r5		# loop max 5000 times
1:
	mfpr	$CSRS,r2
	bbs	$7,r2,1f
	sobgtr	r5,1b
	movab	_tu,r5
	movl	$13,16(r5)		# return TUS_RCVERR
	tstl	(sp)+			# and let turintr handle it
1:
	rsb
#endif

/*
 * BI passive release things.
 */
SCBVEC(passiverel):
	rei				# well that was useless

/*
 * Stray UNIBUS interrupt catch routines
 */
	.data
	.align	2
#define	PJ	PUSHR;jsb _Xustray
	.globl	_catcher
_catcher:
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ

	.globl	_cold
	.globl	_br
	.globl	_cvec
_cold:	.long	1
_br:	.long	0
_cvec:	.long	0

	.text
SCBVEC(ustray):
	blbc	_cold,1f
	mfpr	$IPL,r11
	movl	r11,_br
	subl3	$_catcher+8,(sp)+,r10
	ashl	$-1,r10,r10
	movl	r10,_cvec
	POPR
	rei
1:
	subl3	$_catcher+8,(sp)+,r0
	ashl	$-1,r0,-(sp)
	mfpr	$IPL,-(sp)
	PRINTF(2, "uba?: stray intr ipl %x vec %o\n")
	POPR
	rei

#if VAX630 || VAX650
/*
 * Emulation OpCode jump table:
 *	ONLY GOES FROM 0xf8 (-8) TO 0x3B (59)
 */
#define EMUTABLE	0x43
#define NOEMULATE	.long noemulate
#define	EMULATE(a)	.long _EM/**/a
	.globl	_emJUMPtable
_emJUMPtable:
/* f8 */	EMULATE(ashp);	EMULATE(cvtlp);	NOEMULATE;	NOEMULATE
/* fc */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 00 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 04 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 08 */	EMULATE(cvtps);	EMULATE(cvtsp);	NOEMULATE;	EMULATE(crc)
/* 0c */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 10 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 14 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 18 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 1c */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 20 */	EMULATE(addp4);	EMULATE(addp6);	EMULATE(subp4);	EMULATE(subp6)
/* 24 */	EMULATE(cvtpt);	EMULATE(mulp);	EMULATE(cvttp);	EMULATE(divp)
/* 28 */	NOEMULATE;	EMULATE(cmpc3);	EMULATE(scanc);	EMULATE(spanc)
/* 2c */	NOEMULATE;	EMULATE(cmpc5);	EMULATE(movtc);	EMULATE(movtuc)
/* 30 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
/* 34 */	EMULATE(movp);	EMULATE(cmpp3);	EMULATE(cvtpl);	EMULATE(cmpp4)
/* 38 */	EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc)
#endif

/*
 * Trap and fault vector routines
 */ 
#define	TRAP(a)	pushl $T_/**/a; jbr alltraps

/*
 * Ast delivery (profiling and/or reschedule)
 */
SCBVEC(astflt):
	pushl $0; TRAP(ASTFLT)
SCBVEC(privinflt):
	pushl $0; TRAP(PRIVINFLT)
SCBVEC(xfcflt):
	pushl $0; TRAP(XFCFLT)
SCBVEC(resopflt):
	pushl $0; TRAP(RESOPFLT)
SCBVEC(resadflt):
	pushl $0; TRAP(RESADFLT)
SCBVEC(bptflt):
	pushl $0; TRAP(BPTFLT)
SCBVEC(compatflt):
	TRAP(COMPATFLT);
SCBVEC(kdbintr):
	pushl $0; TRAP(KDBTRAP)
SCBVEC(tracep):
	pushl $0; TRAP(TRCTRAP)
SCBVEC(arithtrap):
	TRAP(ARITHTRAP)
SCBVEC(protflt):
	blbs	(sp)+,segflt
	TRAP(PROTFLT)
segflt:
	TRAP(SEGFLT)

/*
 * The following is called with the stack set up as follows:
 *
 *	  (sp):	Opcode
 *	 4(sp):	Instruction PC
 *	 8(sp):	Operand 1
 *	12(sp):	Operand 2
 *	16(sp):	Operand 3
 *	20(sp):	Operand 4
 *	24(sp):	Operand 5
 *	28(sp):	Operand 6
 *	32(sp):	Operand 7 (unused)
 *	36(sp):	Operand 8 (unused)
 *	40(sp):	Return PC
 *	44(sp):	Return PSL
 *	48(sp): TOS before instruction
 *
 * Each individual routine is called with the stack set up as follows:
 *
 *	  (sp):	Return address of trap handler
 *	 4(sp):	Opcode (will get return PSL)
 *	 8(sp):	Instruction PC
 *	12(sp):	Operand 1
 *	16(sp):	Operand 2
 *	20(sp):	Operand 3
 *	24(sp):	Operand 4
 *	28(sp):	Operand 5
 *	32(sp):	Operand 6
 *	36(sp):	saved register 11
 *	40(sp):	saved register 10
 *	44(sp):	Return PC
 *	48(sp):	Return PSL
 *	52(sp): TOS before instruction
 */

SCBVEC(emulate):
#if VAX630 || VAX650
	movl	r11,32(sp)		# save register r11 in unused operand
	movl	r10,36(sp)		# save register r10 in unused operand
	cvtbl	(sp),r10		# get opcode
	addl2	$8,r10			# shift negative opcodes
	subl3	r10,$EMUTABLE,r11	# forget it if opcode is out of range
	bcs	noemulate
	movl	_emJUMPtable[r10],r10	# call appropriate emulation routine
	jsb	(r10)		# routines put return values into regs 0-5
	movl	32(sp),r11		# restore register r11
	movl	36(sp),r10		# restore register r10
	insv	(sp),$0,$4,44(sp)	# and condition codes in Opcode spot
	addl2	$40,sp			# adjust stack for return
	rei
noemulate:
	addl2	$48,sp			# adjust stack for
#endif
	.word	0xffff			# "reserved instruction fault"
SCBVEC(emulateFPD):
	.word	0xffff			# "reserved instruction fault"
SCBVEC(transflt):
	bitl	$2,(sp)+
	bnequ	tableflt
 	jsb	Fastreclaim		# try and avoid pagein
	TRAP(PAGEFLT)
tableflt: 
	TRAP(TABLEFLT)

alltraps:
	mfpr	$USP,-(sp); calls $0,_trap; mtpr (sp)+,$USP
	incl	_cnt+V_TRAP
	addl2	$8,sp			# pop type, code
	mtpr	$HIGH,$IPL		## dont go to a higher IPL (GROT)
	rei

SCBVEC(syscall):
	pushl	$T_SYSCALL
	mfpr	$USP,-(sp); calls $0,_syscall; mtpr (sp)+,$USP
	incl	_cnt+V_SYSCALL
	addl2	$8,sp			# pop type, code
	mtpr	$HIGH,$IPL		## dont go to a higher IPL (GROT)
	rei

/*
 * System page table
 * Mbmap and Usrptmap are enlarged by CLSIZE entries
 * as they are managed by resource maps starting with index 1 or CLSIZE.
 */ 
#define	vaddr(x)	((((x)-_Sysmap)/4)*NBPG+0x80000000)
#define	SYSMAP(mname, vname, npte)			\
_/**/mname:	.globl	_/**/mname;		\
	.space	(npte)*4;				\
	.globl	_/**/vname;			\
	.set	_/**/vname,vaddr(_/**/mname)
#define	ADDMAP(npte)	.space	(npte)*4

	.data
	.align	2
	SYSMAP(Sysmap	,Sysbase	,SYSPTSIZE	)
	SYSMAP(Forkmap	,forkutl	,UPAGES		)
	SYSMAP(Xswapmap	,xswaputl	,UPAGES		)
	SYSMAP(Xswap2map,xswap2utl	,UPAGES		)
	SYSMAP(Swapmap	,swaputl	,UPAGES		)
	SYSMAP(Pushmap	,pushutl	,UPAGES		)
	SYSMAP(Vfmap	,vfutl		,UPAGES		)
	SYSMAP(CMAP1	,CADDR1		,1		)
	SYSMAP(CMAP2	,CADDR2		,1		)
	SYSMAP(mmap	,vmmap		,1		)
	SYSMAP(alignmap	,alignutl	,1		)	/* XXX */
	SYSMAP(msgbufmap,msgbuf		,MSGBUFPTECNT	)
	SYSMAP(Mbmap	,mbutl		,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE )
#ifdef MFS
#include "../ufs/mfsiom.h"
	/*
	 * Used by the mfs_doio() routine for physical I/O
	 */
	SYSMAP(Mfsiomap	,mfsiobuf	,MFS_MAPREG )
#endif /* MFS */
#ifdef NFS
#include "../nfs/nfsiom.h"
	/*
	 * Used by the nfs_doio() routine for physical I/O
	 */
	SYSMAP(Nfsiomap	,nfsiobuf	,NFS_MAPREG )
#endif /* NFS */
	/*
	 * This is the map used by the kernel memory allocator.
	 * It is expanded as necessary by the special features
	 * that use it.
	 *
	 * XXX: NEED way to compute kmem size from maxusers,
	 * device complement
	 */
	SYSMAP(kmempt	,kmembase	,NKMEMCLUSTERS*CLSIZE )
#ifdef	SYSVSHM
				ADDMAP(	SHMMAXPGS	)
#endif
#ifdef	GPROF
				ADDMAP( 600*CLSIZE	)
#endif
	SYSMAP(ekmempt	,kmemlimit	,0		)

	SYSMAP(UMBAbeg	,umbabeg	,0		)
	SYSMAP(Nexmap	,nexus		,16*MAXNNEXUS	)
#ifdef QBA
#if (QBAPAGES+UBAIOPAGES) > (UBAPAGES+UBAIOPAGES)*NUBA 
	SYSMAP(UMEMmap	,umem		,(QBAPAGES+UBAIOPAGES) )
#else
	SYSMAP(UMEMmap	,umem		,(UBAPAGES+UBAIOPAGES)*NUBA )
#endif
#else /* QBA */
	SYSMAP(UMEMmap	,umem		,(UBAPAGES+UBAIOPAGES)*NUBA )
#endif /* QBA */
#if VAX8600
	SYSMAP(Ioamap	,ioa		,MAXNIOA*IOAMAPSIZ/NBPG	)
#endif
#if VAX8200 || VAX630
	SYSMAP(Clockmap	,ka630clock	,1		)
#endif
#if VAX8200
	/* alas, the clocks on the 8200 and 630 are not quite identical */
	/* they could be shared for now, but this seemed cleaner */
	.globl _ka820clock; .set _ka820clock,_ka630clock
	SYSMAP(Ka820map	,ka820port	,1		)
	SYSMAP(RX50map	,rx50device	,1		)
#ifdef notyet
	SYSMAP(BRAMmap	,ka820bootram	,KA820_BRPAGES	)
	SYSMAP(EEPROMmap,ka820eeprom	,KA820_EEPAGES	)
#endif
#endif
#if VAX630
	SYSMAP(Ka630map	,ka630cpu	,1		)
#endif
#if VAX650
 	SYSMAP(KA650MERRmap	,ka650merr	,1		)
 	SYSMAP(KA650CBDmap	,ka650cbd	,1		)
 	SYSMAP(KA650SSCmap	,ka650ssc	,3		)
 	SYSMAP(KA650IPCRmap	,ka650ipcr	,1		)
 	SYSMAP(KA650CACHEmap	,ka650cache	,KA650_CACHESIZE/NBPG )
#endif
#ifdef QBA
	/*
	 * qvss and qdss don't coexist - one map will suffice
	 * for either. qvss is 256K each and qdss is 64K each.
	 */
#include "qv.h"
#include "qd.h"
#if NQV > 0 || NQD > 0
	SYSMAP(QVmap	,qvmem		,((512*NQV)+(128*NQD)))
#endif
#endif
	SYSMAP(UMBAend	,umbaend	,0		)

	SYSMAP(Usrptmap	,usrpt		,USRPTSIZE+CLSIZE )

eSysmap:
	.globl	_Syssize
	.set	_Syssize,(eSysmap-_Sysmap)/4
	.text

/*
 * Initialization
 *
 * ipl 0x1f; mapen 0; scbb, pcbb, sbr, slr, isp, ksp not set
 */
	.data
	.globl	_cpu
_cpu:	.long	0
	.text
	.globl	start
start:
	.word	0
	mtpr	$0,$ICCS
/* set system control block base and system page table params */
	mtpr	$_scb-0x80000000,$SCBB
	mtpr	$_Sysmap-0x80000000,$SBR
	mtpr	$_Syssize,$SLR
/* double map the kernel into the virtual user addresses of phys mem */
	mtpr	$_Sysmap,$P0BR
	mtpr	$_Syssize,$P0LR
/* set ISP and get cpu type */
	movl	$_intstack+NISP*NBPG,sp
	mfpr	$SID,r0
	movab	_cpu,r1
	extzv	$24,$8,r0,(r1)
/* init RPB */
	movab	_rpb,r0
	movl	r0,(r0)+			# rp_selfref
	movab	_doadump,r1
	movl	r1,(r0)+			# rp_dumprout
	movl	$0x1f,r2
	clrl	r3
1:	addl2	(r1)+,r3; sobgtr r2,1b
	movl	r3,(r0)+			# rp_chksum
/* count up memory; _physmem contains limit */
	clrl	r7
	ashl	$PGSHIFT,_physmem,r8
	decl	r8
1:	pushl	$4; pushl r7; calls $2,_badaddr; tstl r0; bneq 9f
	acbl	r8,$64*1024,r7,1b
9:
#if  VAX630 || VAX650
/* reserve area at top of memory for processor specific use */
	cmpb	_cpu,$VAX_630
	beql	1f
	cmpb	_cpu,$VAX_650
	bneq	2f
	subl2	$32768,r7	# space for Qbus map registers
	brb	2f
1:
	subl2   $4096,r7	# space for console scratchpad
2:
#endif
/* clear memory from kernel bss and pages for proc 0 u. and page table */
	movab	_edata,r6; bicl2 $SYSTEM,r6
	movab	_end,r5; bicl2 $SYSTEM,r5
#ifdef KADB
	subl2	$4,r5
1:	clrl	(r6); acbl r5,$4,r6,1b		# clear just bss
	addl2	$4,r5
	bbc	$6,r11,0f			# check RB_KDB
	bicl3	$SYSTEM,r9,r5			# skip symbol & string tables
	bicl3	$SYSTEM,r9,r6			# r9 obtained from boot
#endif
0:	bisl3	$SYSTEM,r5,r9			# convert to virtual address
	addl2	$NBPG-1,r9			# roundup to next page
	addl2	$(UPAGES*NBPG)+NBPG+NBPG,r5
1:	clrq	(r6); acbl r5,$8,r6,1b
/* trap() and syscall() save r0-r11 in the entry mask (per ../h/reg.h) */
/* panic() is convenient place to save all for debugging */
	bisw2	$0x0fff,_trap
	bisw2	$0x0fff,_syscall
	bisw2	$0x0fff,_panic
	calls	$0,_fixctlrmask
/* initialize system page table: uba vectors and int stack writeable */
	clrl	r2
	movab	eintstack,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1
1:	bisl3	$PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b
/*
 * make rpb read-only as red zone for interrupt stack
 * (scb(s) and UNIvec are write-protected later)
 */
	bicl2	$PG_PROT,_rpbmap
	bisl2	$PG_KR,_rpbmap
/* make kernel text space read-only */
	movab	_etext+NBPG-1,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1
1:	bisl3	$PG_V|PG_URKR,r2,_Sysmap[r2]; aoblss r1,r2,1b
/* make kernel data, bss, read-write */
	bicl3	$SYSTEM,r9,r1; ashl $-PGSHIFT,r1,r1
1:	bisl3	$PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b
/* now go to mapped mode */
	mtpr	$0,$TBIA; mtpr $1,$MAPEN; jmp *$0f; 0:
/* init mem sizes */
	ashl	$-PGSHIFT,r7,_physmem
/* setup context for proc[0] == Scheduler */
	bicl3	$SYSTEM|(NBPG-1),r9,r6	# make phys, page boundary
/* setup page table for proc[0] */
	ashl	$-PGSHIFT,r6,r3			# r3 = btoc(r6)
	bisl3	$PG_V|PG_KW,r3,_Usrptmap	# init first upt entry
	incl	r3
	movab	_usrpt,r0
	mtpr	r0,$TBIS
/* init p0br, p0lr */
	mtpr	r0,$P0BR
	mtpr	$0,$P0LR
/* init p1br, p1lr */
	movab	NBPG(r0),r0
	movl	$0x200000-UPAGES,r1
	mtpr	r1,$P1LR
	mnegl	r1,r1
	moval	-4*UPAGES(r0)[r1],r2
	mtpr	r2,$P1BR
/* setup mapping for UPAGES of _u */
	movl	$UPAGES,r2; movab _u+NBPG*UPAGES,r1; addl2 $UPAGES,r3; jbr 2f
1:	decl	r3
	moval	-NBPG(r1),r1;
	bisl3	$PG_V|PG_URKW,r3,-(r0)
	mtpr	r1,$TBIS
2:	sobgeq	r2,1b
/* initialize (slightly) the pcb */
	movab	UPAGES*NBPG(r1),PCB_KSP(r1)
	mnegl	$1,PCB_ESP(r1)
	mnegl	$1,PCB_SSP(r1)
	movl	r1,PCB_USP(r1)
	mfpr	$P0BR,PCB_P0BR(r1)
	mfpr	$P0LR,PCB_P0LR(r1)
	movb	$4,PCB_P0LR+3(r1)		# disable ast
	mfpr	$P1BR,PCB_P1BR(r1)
	mfpr	$P1LR,PCB_P1LR(r1)
	movl	$CLSIZE,PCB_SZPT(r1)		# init u.u_pcb.pcb_szpt
	movl	r9,PCB_R9(r1)
	movl	r10,PCB_R10(r1)
	movl	r11,PCB_R11(r1)
	movab	1f,PCB_PC(r1)			# initial pc
	clrl	PCB_PSL(r1)			# mode(k,k), ipl=0
	ashl	$PGSHIFT,r3,r3
	mtpr	r3,$PCBB			# first pcbb
/* set regs, p0br, p0lr, p1br, p1lr, astlvl, ksp and change to kernel mode */
	ldpctx
	rei
/* put signal trampoline code in u. area */
1:	movab	_u,r0
	movc3	$19,sigcode,PCB_SIGC(r0)
/* save boot device in global _bootdev */
	movl	r10,_bootdev
/* save reboot flags in global _boothowto */
	movl	r11,_boothowto
#ifdef KADB
/* save end of symbol & string table in global _bootesym */
	subl3	$NBPG-1,r9,_bootesym
#endif
/* calculate firstaddr, and call main() */
	bicl3	$SYSTEM,r9,r0; ashl $-PGSHIFT,r0,-(sp)
	addl2	$UPAGES+1,(sp); calls $1,_main
/* proc[1] == /etc/init now running here; run icode */
	pushl	$PSL_CURMOD|PSL_PRVMOD; pushl $0; rei

/* signal trampoline code: it is known that this code takes exactly 19 bytes */
/* in ../vax/pcb.h and in the movc3 above */
sigcode:
	calls	$4,8(pc)	# params pushed by sendsig
	movl	sp,ap		# calls frame built by sendsig
	chmk	$SYS_sigreturn	# cleanup mask and onsigstack
	halt			# sigreturn() does not return!
	.word	0x3f		# registers 0-5
	callg	(ap),*16(ap)	# call the signal handler
	ret			# return to code above

	.globl	_icode
	.globl	_initflags
	.globl	_szicode
/*
 * Icode is copied out to process 1 to exec /etc/init.
 * If the exec fails, process 1 exits.
 */
_icode:
	pushab	b`argv-l0(pc)
l0:	pushab	b`init-l1(pc)
l1:	pushl	$2
	movl	sp,ap
	chmk	$SYS_execv
	pushl	r0
	chmk	$SYS_exit

init:	.asciz	"/sbin/init"
	.align	2
_initflags:
	.long	0
argv:	.long	init+6-_icode
	.long	_initflags-_icode
	.long	0
_szicode:
	.long	_szicode-_icode

/*
 * Primitives
 */ 

#ifdef GPROF
#define	ENTRY(name, regs) \
	.globl _/**/name; .align 1; _/**/name: .word regs; jsb mcount
#define	JSBENTRY(name, regs) \
	.globl _/**/name; _/**/name: \
	movl fp,-(sp); movab -12(sp),fp; pushr $(regs); jsb mcount; \
	popr $(regs); movl (sp)+,fp
#else
#define	ENTRY(name, regs) \
	.globl _/**/name; .align 1; _/**/name: .word regs
#define	JSBENTRY(name, regs) \
	.globl _/**/name; _/**/name:
#endif GPROF
#define R0 0x01
#define R1 0x02
#define R2 0x04
#define R3 0x08
#define R4 0x10
#define R5 0x20
#define R6 0x40

/*
 * badaddr(addr, len)
 *	see if access addr with a len type instruction causes a machine check
 *	len is length of access (1=byte, 2=short, 4=long)
 */
	.globl	_badaddr
_badaddr:
	.word	0
	movl	$1,r0
	mfpr	$IPL,r1
	mtpr	$HIGH,$IPL
	movl	4(ap),r3
	movl	8(ap),r4
	movab	2f,nofault		# jump to 2f on machcheck
	bbc	$0,r4,1f; tstb	(r3)
1:	bbc	$1,r4,1f; tstw	(r3)
1:	bbc	$2,r4,1f; tstl	(r3)
1:	clrl	r0			# made it w/o machine checks
2:	clrl	nofault
	mtpr	r1,$IPL
	ret

/*
 * update profiling information for the user
 * addupc(pc, &u.u_prof, ticks)
 */
ENTRY(addupc, 0)
	movl	8(ap),r2		# &u.u_prof
	subl3	8(r2),4(ap),r0		# corrected pc
	blss	9f
	extzv	$1,$31,r0,r0		# logical right shift
	extzv	$1,$31,12(r2),r1	# ditto for scale
	emul	r1,r0,$0,r0
	ashq	$-14,r0,r0
	tstl	r1
	bneq	9f
	bicl2	$1,r0
	cmpl	r0,4(r2)		# length
	bgequ	9f
	addl2	(r2),r0			# base
	probew	$3,$2,(r0)
	beql	8f
	addw2	12(ap),(r0)
9:
	ret
8:
	clrl	12(r2)
	ret

/*
 * Copy a null terminated string from the user address space into
 * the kernel address space.
 *
 * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
 */
ENTRY(copyinstr, R6)
	movl	12(ap),r6		# r6 = max length
	jlss	8f
	movl	4(ap),r1		# r1 = user address
	bicl3	$~(NBPG*CLSIZE-1),r1,r2	# r2 = bytes on first page
	subl3	r2,$NBPG*CLSIZE,r2
	movl	8(ap),r3		# r3 = kernel address
1:
	cmpl	r6,r2			# r2 = min(bytes on page, length left);
	jgeq	2f
	movl	r6,r2
2:
	prober	$3,r2,(r1)		# bytes accessible?
	jeql	8f
	subl2	r2,r6			# update bytes left count
#ifdef NOSUBSINST
	# fake the locc instr. for processors that don't have it
	movl	r2,r0
6:
	tstb	(r1)+
	jeql	5f
	sobgtr	r0,6b
	jbr	7f
5:
	decl	r1
	jbr	3f
7:
#else
	locc	$0,r2,(r1)		# null byte found?
	jneq	3f
#endif
	subl2	r2,r1			# back up pointer updated by `locc'
	movc3	r2,(r1),(r3)		# copy in next piece
	movl	$(NBPG*CLSIZE),r2	# check next page
	tstl	r6			# run out of space?
	jneq	1b
	movl	$ENOENT,r0		# set error code and return
	jbr	9f
3:
	tstl	16(ap)			# return length?
	beql	4f
	subl3	r6,12(ap),r6		# actual len = maxlen - unused pages
	subl2	r0,r6			#	- unused on this page
	addl3	$1,r6,*16(ap)		#	+ the null byte
4:
	subl2	r0,r2			# r2 = number of bytes to move
	subl2	r2,r1			# back up pointer updated by `locc'
	incl	r2			# copy null byte as well
	movc3	r2,(r1),(r3)		# copy in last piece
	clrl	r0			# redundant
	ret
8:
	movl	$EFAULT,r0
9:
	tstl	16(ap)
	beql	1f
	subl3	r6,12(ap),*16(ap)
1:
	ret

/*
 * Copy a null terminated string from the kernel
 * address space to the user address space.
 *
 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
 */
ENTRY(copyoutstr, R6)
	movl	12(ap),r6		# r6 = max length
	jlss	8b
	movl	4(ap),r1		# r1 = kernel address
	movl	8(ap),r3		# r3 = user address
	bicl3	$~(NBPG*CLSIZE-1),r3,r2	# r2 = bytes on first page
	subl3	r2,$NBPG*CLSIZE,r2
1:
	cmpl	r6,r2			# r2 = min(bytes on page, length left);
	jgeq	2f
	movl	r6,r2
2:
	probew	$3,r2,(r3)		# bytes accessible?
	jeql	8b
	subl2	r2,r6			# update bytes left count
#ifdef NOSUBSINST
	# fake the locc instr. for processors that don't have it
	movl	r2,r0
6:
	tstb	(r1)+
	jeql	5f
	sobgtr	r0,6b
	jbr	7f
5:
	decl	r1
	jbr	3b
7:
#else
	locc	$0,r2,(r1)		# null byte found?
	jneq	3b
#endif
	subl2	r2,r1			# back up pointer updated by `locc'
	movc3	r2,(r1),(r3)		# copy in next piece
	movl	$(NBPG*CLSIZE),r2	# check next page
	tstl	r6			# run out of space?
	jneq	1b
	movl	$ENOENT,r0		# set error code and return
	jbr	9b

/*
 * Copy a null terminated string from one point to another in
 * the kernel address space.
 *
 * copystr(fromaddr, toaddr, maxlength, &lencopied)
 */
ENTRY(copystr, R6)
	movl	12(ap),r6		# r6 = max length
	jlss	8b
	movl	4(ap),r1		# r1 = src address
	movl	8(ap),r3		# r3 = dest address
1:
	movzwl	$65535,r2		# r2 = bytes in first chunk
	cmpl	r6,r2			# r2 = min(bytes in chunk, length left);
	jgeq	2f
	movl	r6,r2
2:
	subl2	r2,r6			# update bytes left count
#ifdef NOSUBSINST
	# fake the locc instr. for processors that don't have it
	movl	r2,r0
6:
	tstb	(r1)+
	jeql	5f
	sobgtr	r0,6b
	jbr	7f
5:
	decl	r1
	jbr	3b
7:
#else
	locc	$0,r2,(r1)		# null byte found?
	jneq	3b
#endif
	subl2	r2,r1			# back up pointer updated by `locc'
	movc3	r2,(r1),(r3)		# copy in next piece
	tstl	r6			# run out of space?
	jneq	1b
	movl	$ENOENT,r0		# set error code and return
	jbr	9b

/* 
 * Copy specified amount of data from user space into the kernel
 * Copyin(from, to, len)
 *	r1 == from (user source address)
 *	r3 == to (kernel destination address)
 *	r5 == length
 */
	.align	1
JSBENTRY(Copyin, R1|R3|R5)
	cmpl	r5,$(NBPG*CLSIZE)	# probing one page or less ?
	bgtru	1f			# no
	prober	$3,r5,(r1)		# bytes accessible ?
	beql	ersb			# no
	movc3	r5,(r1),(r3)
/*	clrl	r0			# redundant */
	rsb
1:
	blss	ersb			# negative length?
	pushl	r6			# r6 = length
	movl	r5,r6
	bicl3	$~(NBPG*CLSIZE-1),r1,r0	# r0 = bytes on first page
	subl3	r0,$(NBPG*CLSIZE),r0
	addl2	$(NBPG*CLSIZE),r0	# plus one additional full page
	jbr	2f

ciloop:
	movc3	r0,(r1),(r3)
	movl	$(2*NBPG*CLSIZE),r0	# next amount to move
2:
	cmpl	r0,r6
	bleq	3f
	movl	r6,r0
3:
	prober	$3,r0,(r1)		# bytes accessible ?
	beql	ersb1			# no
	subl2	r0,r6			# last move?
	bneq	ciloop			# no

	movc3	r0,(r1),(r3)
/*	clrl	r0			# redundant */
	movl	(sp)+,r6		# restore r6
	rsb

ersb1:
	movl	(sp)+,r6		# restore r6
ersb:
	movl	$EFAULT,r0
	rsb

/* 
 * Copy specified amount of data from kernel to the user space
 * Copyout(from, to, len)
 *	r1 == from (kernel source address)
 *	r3 == to (user destination address)
 *	r5 == length
 */
	.align	1
JSBENTRY(Copyout, R1|R3|R5)
	cmpl	r5,$(NBPG*CLSIZE)	# moving one page or less ?
	bgtru	1f			# no
	probew	$3,r5,(r3)		# bytes writeable?
	beql	ersb			# no
	movc3	r5,(r1),(r3)
/*	clrl	r0			# redundant */
	rsb
1:
	blss	ersb			# negative length?
	pushl	r6			# r6 = length
	movl	r5,r6
	bicl3	$~(NBPG*CLSIZE-1),r3,r0	# r0 = bytes on first page
	subl3	r0,$(NBPG*CLSIZE),r0
	addl2	$(NBPG*CLSIZE),r0	# plus one additional full page
	jbr	2f

coloop:
	movc3	r0,(r1),(r3)
	movl	$(2*NBPG*CLSIZE),r0	# next amount to move
2:
	cmpl	r0,r6
	bleq	3f
	movl	r6,r0
3:
	probew	$3,r0,(r3)		# bytes writeable?
	beql	ersb1			# no
	subl2	r0,r6			# last move?
	bneq	coloop			# no

	movc3	r0,(r1),(r3)
/*	clrl	r0			# redundant */
	movl	(sp)+,r6		# restore r6
	rsb

/*
 * savectx is like setjmp but saves all registers.
 * Called before swapping out the u. area, restored by resume()
 * below.
 */
#define PCLOC 16	/* location of pc in calls frame */
#define APLOC 8		/* location of ap,fp in calls frame */

ENTRY(savectx, 0)
	movl	4(ap),r0
	movq	r6,(r0)+
	movq	r8,(r0)+
	movq	r10,(r0)+
	movq	APLOC(fp),(r0)+	# save ap, fp
	addl3	$8,ap,(r0)+	# save sp
	movl	PCLOC(fp),(r0)	# save pc
	clrl	r0
	ret

#ifdef KADB
/*
 * C library -- reset, setexit
 *
 *	reset(x)
 * will generate a "return" from
 * the last call to
 *	setexit()
 * by restoring r6 - r12, ap, fp
 * and doing a return.
 * The returned value is x; on the original
 * call the returned value is 0.
 */
ENTRY(setexit, 0)
	movab	setsav,r0
	movq	r6,(r0)+
	movq	r8,(r0)+
	movq	r10,(r0)+
	movq	8(fp),(r0)+		# ap, fp
	movab	4(ap),(r0)+		# sp
	movl	16(fp),(r0)		# pc
	clrl	r0
	ret

ENTRY(reset, 0)
	movl	4(ap),r0	# returned value
	movab	setsav,r1
	movq	(r1)+,r6
	movq	(r1)+,r8
	movq	(r1)+,r10
	movq	(r1)+,r12
	movl	(r1)+,sp
	jmp 	*(r1)

	.data
	.align  2
setsav:	.space	10*4
	.text
#endif

	.globl	_whichqs
	.globl	_qs
	.globl	_cnt

	.globl	_noproc
	.comm	_noproc,4
	.globl	_runrun
	.comm	_runrun,4

/*
 * The following primitives use the fancy VAX instructions
 * much like VMS does.  _whichqs tells which of the 32 queues _qs
 * have processes in them.  Setrq puts processes into queues, Remrq
 * removes them from queues.  The running process is on no queue,
 * other processes are on a queue related to p->p_pri, divided by 4
 * actually to shrink the 0-127 range of priorities into the 32 available
 * queues.
 */

/*
 * Setrq(p), using fancy VAX instructions.
 *
 * Call should be made at splclock(), and p->p_stat should be SRUN
 */
	.align	1
JSBENTRY(Setrq, R0)
	tstl	P_RLINK(r0)		## firewall: p->p_rlink must be 0
	beql	set1			##
	pushab	set3			##
	calls	$1,_panic		##
set1:
	movzbl	P_PRI(r0),r1		# put on queue which is p->p_pri / 4
	ashl	$-2,r1,r1
	movaq	_qs[r1],r2
	insque	(r0),*4(r2)		# at end of queue
	bbss	r1,_whichqs,set2	# mark queue non-empty
set2:
	rsb

set3:	.asciz	"setrq"

/*
 * Remrq(p), using fancy VAX instructions
 *
 * Call should be made at splclock().
 */
	.align	1
JSBENTRY(Remrq, R0)
	movzbl	P_PRI(r0),r1
	ashl	$-2,r1,r1
	bbsc	r1,_whichqs,rem1
	pushab	rem3			# it wasn't recorded to be on its q
	calls	$1,_panic
rem1:
	remque	(r0),r2
	beql	rem2
	bbss	r1,_whichqs,rem2
rem2:
	clrl	P_RLINK(r0)		## for firewall checking
	rsb

rem3:	.asciz	"remrq"

/*
 * Masterpaddr is the p->p_addr of the running process on the master
 * processor.  When a multiprocessor system, the slave processors will have
 * an array of slavepaddr's.
 */
	.globl	_masterpaddr
	.data
_masterpaddr:
	.long	0

	.text
sw0:	.asciz	"swtch"

/*
 * When no processes are on the runq, Swtch branches to idle
 * to wait for something to come ready.
 */
	.globl	Idle
Idle: idle:
	movl	$1,_noproc
	mtpr	$0,$IPL			# must allow interrupts here
1:
	tstl	_whichqs		# look for non-empty queue
	bneq	sw1
	brb	1b

badsw:	pushab	sw0
	calls	$1,_panic
	/*NOTREACHED*/

/*
 * Swtch(), using fancy VAX instructions
 */
	.align	1
JSBENTRY(Swtch, 0)
	incl	_cnt+V_SWTCH
sw1:	ffs	$0,$32,_whichqs,r0	# look for non-empty queue
	beql	idle			# if none, idle
	mtpr	$0x18,$IPL		# lock out all so _whichqs==_qs
	bbcc	r0,_whichqs,sw1		# proc moved via interrupt
	movaq	_qs[r0],r1
	remque	*(r1),r2		# r2 = p = highest pri process
	bvs	badsw			# make sure something was there
	beql	sw2
	insv	$1,r0,$1,_whichqs	# still more procs in this queue
sw2:
	clrl	_noproc
	clrl	_runrun
#ifdef notdef
	tstl	P_WCHAN(r2)		## firewalls
	bneq	badsw			##
	cmpb	P_STAT(r2),$SRUN	##
	bneq	badsw			##
#endif
	clrl	P_RLINK(r2)		##
	movl	*P_ADDR(r2),r0
#ifdef notdef
	cmpl	r0,_masterpaddr		# resume of current proc is easy
	beql	res0
#endif
	movl	r0,_masterpaddr
	ashl	$PGSHIFT,r0,r0		# r0 = pcbb(p)
/* fall into... */

/*
 * Resume(pf)
 */
JSBENTRY(Resume, R0)
	mtpr	$HIGH,$IPL			# no interrupts, please
	movl	_CMAP2,_u+PCB_CMAP2	# yech
	svpctx
	mtpr	r0,$PCBB
	ldpctx
	movl	_u+PCB_CMAP2,_CMAP2	# yech
	mtpr	$_CADDR2,$TBIS
res0:
	tstl	_u+PCB_SSWAP
	bneq	res1
	rei
res1:
	movl	_u+PCB_SSWAP,r0		# restore alternate saved context
	clrl	_u+PCB_SSWAP
	movq	(r0)+,r6			# restore r6, r7
	movq	(r0)+,r8			# restore r8, r9
	movq	(r0)+,r10			# restore r10, r11
	movq	(r0)+,r12			# restore ap, fp
	movl	(r0)+,r1			# saved sp
	cmpl	r1,sp				# must be a pop
	bgequ	1f
	pushab	2f
	calls	$1,_panic
	/* NOTREACHED */
1:
	movl	r1,sp				# restore sp
	pushl	$PSL_PRVMOD			# return psl
	pushl	(r0)				# address to return to
	rei

2:	.asciz	"ldctx"

/*
 * {fu,su},{byte,word}, all massaged by asm.sed to jsb's
 */
	.align	1
JSBENTRY(Fuword, R0)
	prober	$3,$4,(r0)
	beql	fserr
	movl	(r0),r0
	rsb
fserr:
	mnegl	$1,r0
	rsb

	.align	1
JSBENTRY(Fubyte, R0)
	prober	$3,$1,(r0)
	beql	fserr
	movzbl	(r0),r0
	rsb

	.align	1
JSBENTRY(Suword, R0|R1)
	probew	$3,$4,(r0)
	beql	fserr
	movl	r1,(r0)
	clrl	r0
	rsb

	.align	1
JSBENTRY(Subyte, R0|R1)
	probew	$3,$1,(r0)
	beql	fserr
	movb	r1,(r0)
	clrl	r0
	rsb

/*
 * Copy 1 relocation unit (NBPG bytes)
 * from user virtual address to physical address
 */
ENTRY(copyseg, 0)
	bisl3	$PG_V|PG_KW,8(ap),_CMAP2
	mtpr	$_CADDR2,$TBIS	# invalidate entry for copy 
	movc3	$NBPG,*4(ap),_CADDR2
	ret

/*
 * zero out physical memory
 * specified in relocation units (NBPG bytes)
 */
ENTRY(clearseg, 0)
	bisl3	$PG_V|PG_KW,4(ap),_CMAP1
	mtpr	$_CADDR1,$TBIS
	movc5	$0,(sp),$0,$NBPG,_CADDR1
	ret

/*
 * Check address.
 * Given virtual address, byte count, and rw flag
 * returns 0 on no access.
 */
ENTRY(useracc, 0)
	movl	4(ap),r0		# get va
	movl	8(ap),r1		# count
	tstl	12(ap)			# test for read access ?
	bneq	userar			# yes
	cmpl	$NBPG,r1			# can we do it in one probe ?
	bgeq	uaw2			# yes
uaw1:
	probew	$3,$NBPG,(r0)
	beql	uaerr			# no access
	addl2	$NBPG,r0
	acbl	$NBPG+1,$-NBPG,r1,uaw1
uaw2:
	probew	$3,r1,(r0)
	beql	uaerr
	movl	$1,r0
	ret

userar:
	cmpl	$NBPG,r1
	bgeq	uar2
uar1:
	prober	$3,$NBPG,(r0)
	beql	uaerr
	addl2	$NBPG,r0
	acbl	$NBPG+1,$-NBPG,r1,uar1
uar2:
	prober	$3,r1,(r0)
	beql	uaerr
	movl	$1,r0
	ret
uaerr:
	clrl	r0
	ret

/*
 * kernacc - check for kernel access privileges
 *
 * We can't use the probe instruction directly because
 * it ors together current and previous mode.
 */
 ENTRY(kernacc, 0)
	movl	4(ap),r0	# virtual address
	bbcc	$31,r0,kacc1
	bbs	$30,r0,kacerr
	mfpr	$SBR,r2		# address and length of page table (system)
	bbss	$31,r2,0f; 0:
	mfpr	$SLR,r3
	brb	kacc2
kacc1:
	bbsc	$30,r0,kacc3
	mfpr	$P0BR,r2	# user P0
	mfpr	$P0LR,r3
	brb	kacc2
kacc3:
	mfpr	$P1BR,r2	# user P1 (stack)
	mfpr	$P1LR,r3
kacc2:
	addl3	8(ap),r0,r1	# ending virtual address
	addl2	$NBPG-1,r1
	ashl	$-PGSHIFT,r0,r0
	ashl	$-PGSHIFT,r1,r1
	bbs	$31,4(ap),kacc6
	bbc	$30,4(ap),kacc6
	cmpl	r0,r3		# user stack
	blss	kacerr		# address too low
	brb	kacc4
kacc6:
	cmpl	r1,r3		# compare last page to P0LR or SLR
	bgtr	kacerr		# address too high
kacc4:	
	movl	(r2)[r0],r3
	bbc	$31,4(ap),kacc4a
	bbc	$31,r3,kacerr	# valid bit is off
kacc4a:
	cmpzv	$27,$4,r3,$1	# check protection code
	bleq	kacerr		# no access allowed
	tstb	12(ap)
	bneq	kacc5		# only check read access
	cmpzv	$27,$2,r3,$3	# check low 2 bits of prot code
	beql	kacerr		# no write access
kacc5:
	aoblss	r1,r0,kacc4	# next page
	movl	$1,r0		# no errors
	ret
kacerr:
	clrl	r0		# error
	ret
/*
 * Extracted and unrolled most common case of pagein (hopefully):
 *	resident and not on free list (reclaim of page is purely
 *	for the purpose of simulating a reference bit)
 *
 * Built in constants:
 *	CLSIZE of 2, any bit fields in pte's
 */
	.text
	.globl	Fastreclaim
Fastreclaim:
	PUSHR
#ifdef GPROF
	movl	fp,-(sp)
	movab	12(sp),fp
	jsb	mcount
	movl	(sp)+,fp
#endif GPROF
	extzv	$9,$23,28(sp),r3	# virtual address
	bicl2	$1,r3			# v = clbase(btop(virtaddr)); 
	movl	_u+U_PROCP,r5		# p = u.u_procp 
					# from vtopte(p, v) ...
	movl	$1,r2			# type = CTEXT;
	cmpl	r3,P_TSIZE(r5)
	jlssu	1f			# if (isatsv(p, v)) {
	addl3	P_TSIZE(r5),P_DSIZE(r5),r0
	cmpl	r3,r0
	jgequ	2f
	clrl	r2			#	type = !CTEXT;
1:
	ashl	$2,r3,r4
	addl2	P_P0BR(r5),r4		#	tptopte(p, vtotp(p, v));
	jbr	3f
2:
	cvtwl	P_SZPT(r5),r4		# } else (isassv(p, v)) {
	ashl	$7,r4,r4
	subl2	$0x400000,r4
	addl2	r3,r4
	ashl	$2,r4,r4
	addl2	P_P0BR(r5),r4		#	sptopte(p, vtosp(p, v));
	clrl	r2			# 	type = !CTEXT;
3:					# }
	bitb	$0x82,3(r4)
	beql	2f			# if (pte->pg_v || pte->pg_fod)
	POPR; rsb			#	let pagein handle it
2:
	bicl3	$0xffe00000,(r4),r0
	jneq	2f			# if (pte->pg_pfnum == 0)
	POPR; rsb			# 	let pagein handle it 
2:
	subl2	_firstfree,r0
	ashl	$-1,r0,r0	
	incl	r0			# pgtocm(pte->pg_pfnum) 
	mull2	$SZ_CMAP,r0
	addl2	_cmap,r0		# &cmap[pgtocm(pte->pg_pfnum)] 
	tstl	r2
	jeql	2f			# if (type == CTEXT &&
	jbc	$C_INTRANS,(r0),2f	#     c_intrans)
	POPR; rsb			# 	let pagein handle it
2:
	jbc	$C_FREE,(r0),2f		# if (c_free)
	POPR; rsb			# 	let pagein handle it 
2:
	bisb2	$0x80,3(r4)		# pte->pg_v = 1;
	jbc	$26,4(r4),2f		# if (anycl(pte, pg_m) 
	bisb2	$0x04,3(r4)		#	pte->pg_m = 1;
2:
	bicw3	$0x7f,2(r4),r0
	bicw3	$0xff80,6(r4),r1
	bisw3	r0,r1,6(r4)		# distcl(pte);
	ashl	$PGSHIFT,r3,r0
	mtpr	r0,$TBIS
	addl2	$NBPG,r0
	mtpr	r0,$TBIS		# tbiscl(v); 
	tstl	r2
	jeql	2f			# if (type == CTEXT) 
	movl	P_TEXTP(r5),r0
	movl	X_CADDR(r0),r5		# for (p = p->p_textp->x_caddr; p; ) {
	jeql	2f
	ashl	$2,r3,r3
3:
	addl3	P_P0BR(r5),r3,r0	#	tpte = tptopte(p, tp);
	bisb2	$1,P_FLAG+3(r5)		#	p->p_flag |= SPTECHG;
	movl	(r4),(r0)+		#	for (i = 0; i < CLSIZE; i++)
	movl	4(r4),(r0)		#		tpte[i] = pte[i];
	movl	P_XLINK(r5),r5		#	p = p->p_xlink;
	jneq	3b			# }
2:					# collect a few statistics...
	incl	_u+U_RU+RU_MINFLT	# u.u_ru.ru_minflt++;
	moval	_cnt,r0
	incl	V_FAULTS(r0)		# cnt.v_faults++; 
	incl	V_PGREC(r0)		# cnt.v_pgrec++;
	incl	V_FASTPGREC(r0)		# cnt.v_fastpgrec++;
	incl	V_TRAP(r0)		# cnt.v_trap++;
	POPR
	addl2	$8,sp			# pop pc, code
	mtpr	$HIGH,$IPL		## dont go to a higher IPL (GROT)
	rei
	.globl	_Xkdbintr0
	.align	2
_Xkdbintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*0)
	pushl	$0
	calls	$1,_kdbintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xrkintr0
	.align	2
_Xrkintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*1)
	pushl	$0
	calls	$1,_rkintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xtmintr0
	.align	2
_Xtmintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*2)
	pushl	$0
	calls	$1,_tmintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xutintr0
	.align	2
_Xutintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*3)
	pushl	$0
	calls	$1,_utintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xtmscpintr0
	.align	2
_Xtmscpintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*4)
	pushl	$0
	calls	$1,_tmscpintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xupintr0
	.align	2
_Xupintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*5)
	pushl	$0
	calls	$1,_upintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xudaintr0
	.align	2
_Xudaintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*6)
	pushl	$0
	calls	$1,_udaintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xidcintr0
	.align	2
_Xidcintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*7)
	pushl	$0
	calls	$1,_idcintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xrlintr0
	.align	2
_Xrlintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*8)
	pushl	$0
	calls	$1,_rlintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdhrint0
	.align	2
_Xdhrint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*9)
	pushl	$0
	calls	$1,_dhrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdhxint0
	.align	2
_Xdhxint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*10)
	pushl	$0
	calls	$1,_dhxint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmintr0
	.align	2
_Xdmintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*11)
	pushl	$0
	calls	$1,_dmintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdhrint1
	.align	2
_Xdhrint1:
	pushr	$0x3f
	incl	_fltintrcnt+(4*12)
	pushl	$1
	calls	$1,_dhrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdhxint1
	.align	2
_Xdhxint1:
	pushr	$0x3f
	incl	_fltintrcnt+(4*13)
	pushl	$1
	calls	$1,_dhxint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzrint0
	.align	2
_Xdzrint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*14)
	pushl	$0
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint0
	.align	2
_Xdzxint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*15)
	movl	$0,r0
	jmp	dzdma

	.globl	_Xdzrint1
	.align	2
_Xdzrint1:
	pushr	$0x3f
	incl	_fltintrcnt+(4*16)
	pushl	$1
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint1
	.align	2
_Xdzxint1:
	pushr	$0x3f
	incl	_fltintrcnt+(4*17)
	movl	$1,r0
	jmp	dzdma

	.globl	_Xdzrint2
	.align	2
_Xdzrint2:
	pushr	$0x3f
	incl	_fltintrcnt+(4*18)
	pushl	$2
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint2
	.align	2
_Xdzxint2:
	pushr	$0x3f
	incl	_fltintrcnt+(4*19)
	movl	$2,r0
	jmp	dzdma

	.globl	_Xdzrint3
	.align	2
_Xdzrint3:
	pushr	$0x3f
	incl	_fltintrcnt+(4*20)
	pushl	$3
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint3
	.align	2
_Xdzxint3:
	pushr	$0x3f
	incl	_fltintrcnt+(4*21)
	movl	$3,r0
	jmp	dzdma

	.globl	_Xdzrint4
	.align	2
_Xdzrint4:
	pushr	$0x3f
	incl	_fltintrcnt+(4*22)
	pushl	$4
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint4
	.align	2
_Xdzxint4:
	pushr	$0x3f
	incl	_fltintrcnt+(4*23)
	movl	$4,r0
	jmp	dzdma

	.globl	_Xdzrint5
	.align	2
_Xdzrint5:
	pushr	$0x3f
	incl	_fltintrcnt+(4*24)
	pushl	$5
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint5
	.align	2
_Xdzxint5:
	pushr	$0x3f
	incl	_fltintrcnt+(4*25)
	movl	$5,r0
	jmp	dzdma

	.globl	_Xdzrint6
	.align	2
_Xdzrint6:
	pushr	$0x3f
	incl	_fltintrcnt+(4*26)
	pushl	$6
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint6
	.align	2
_Xdzxint6:
	pushr	$0x3f
	incl	_fltintrcnt+(4*27)
	movl	$6,r0
	jmp	dzdma

	.globl	_Xdzrint7
	.align	2
_Xdzrint7:
	pushr	$0x3f
	incl	_fltintrcnt+(4*28)
	pushl	$7
	calls	$1,_dzrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdzxint7
	.align	2
_Xdzxint7:
	pushr	$0x3f
	incl	_fltintrcnt+(4*29)
	movl	$7,r0
	jmp	dzdma

	.globl	_Xtsintr0
	.align	2
_Xtsintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*30)
	pushl	$0
	calls	$1,_tsintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmfsrint0
	.align	2
_Xdmfsrint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*31)
	pushl	$0
	calls	$1,_dmfsrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmfsxint0
	.align	2
_Xdmfsxint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*32)
	pushl	$0
	calls	$1,_dmfsxint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmfdaint0
	.align	2
_Xdmfdaint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*33)
	pushl	$0
	calls	$1,_dmfdaint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmfdbint0
	.align	2
_Xdmfdbint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*34)
	pushl	$0
	calls	$1,_dmfdbint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmfrint0
	.align	2
_Xdmfrint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*35)
	pushl	$0
	calls	$1,_dmfrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmfxint0
	.align	2
_Xdmfxint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*36)
	pushl	$0
	calls	$1,_dmfxint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmflint0
	.align	2
_Xdmflint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*37)
	pushl	$0
	calls	$1,_dmflint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmzrinta0
	.align	2
_Xdmzrinta0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*38)
	pushl	$0
	calls	$1,_dmzrinta
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmzxinta0
	.align	2
_Xdmzxinta0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*39)
	pushl	$0
	calls	$1,_dmzxinta
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmzrintb0
	.align	2
_Xdmzrintb0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*40)
	pushl	$0
	calls	$1,_dmzrintb
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmzxintb0
	.align	2
_Xdmzxintb0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*41)
	pushl	$0
	calls	$1,_dmzxintb
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmzrintc0
	.align	2
_Xdmzrintc0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*42)
	pushl	$0
	calls	$1,_dmzrintc
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdmzxintc0
	.align	2
_Xdmzxintc0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*43)
	pushl	$0
	calls	$1,_dmzxintc
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdhurint0
	.align	2
_Xdhurint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*44)
	pushl	$0
	calls	$1,_dhurint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdhuxint0
	.align	2
_Xdhuxint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*45)
	pushl	$0
	calls	$1,_dhuxint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xlpintr0
	.align	2
_Xlpintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*46)
	pushl	$0
	calls	$1,_lpintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xqvkint0
	.align	2
_Xqvkint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*47)
	pushl	$0
	calls	$1,_qvkint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xqvvint0
	.align	2
_Xqvvint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*48)
	pushl	$0
	calls	$1,_qvvint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xqddint0
	.align	2
_Xqddint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*49)
	pushl	$0
	calls	$1,_qddint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xqdaint0
	.align	2
_Xqdaint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*50)
	pushl	$0
	calls	$1,_qdaint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xqdiint0
	.align	2
_Xqdiint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*51)
	pushl	$0
	calls	$1,_qdiint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xecrint0
	.align	2
_Xecrint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*52)
	pushl	$0
	calls	$1,_ecrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xeccollide0
	.align	2
_Xeccollide0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*53)
	pushl	$0
	calls	$1,_eccollide
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xecxint0
	.align	2
_Xecxint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*54)
	pushl	$0
	calls	$1,_ecxint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xdeintr0
	.align	2
_Xdeintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*55)
	pushl	$0
	calls	$1,_deintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xilrint0
	.align	2
_Xilrint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*56)
	pushl	$0
	calls	$1,_ilrint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xilcint0
	.align	2
_Xilcint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*57)
	pushl	$0
	calls	$1,_ilcint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xexcdint0
	.align	2
_Xexcdint0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*58)
	pushl	$0
	calls	$1,_excdint
	popr	$0x3f
	incl	_cnt+V_INTR
	rei

	.globl	_Xqeintr0
	.align	2
_Xqeintr0:
	pushr	$0x3f
	incl	_fltintrcnt+(4*59)
	pushl	$0
	calls	$1,_qeintr
	popr	$0x3f
	incl	_cnt+V_INTR
	rei


	.globl	_intrnames

	.globl	_eintrnames
	.data
_intrnames:
	.asciz	"clock"
	.asciz	"cnr"
	.asciz	"cnx"
	.asciz	"tur"
	.asciz	"tux"
	.asciz	"mba0"
	.asciz	"mba1"
	.asciz	"mba2"
	.asciz	"mba3"
	.asciz	"uba0"
	.asciz	"uba1"
	.asciz	"uba2"
	.asciz	"uba3"
	.asciz	"kdb0"
	.asciz	"rk0"
	.asciz	"tm0"
	.asciz	"ut0"
	.asciz	"tmscp0"
	.asciz	"up0"
	.asciz	"uda0"
	.asciz	"idc0"
	.asciz	"rl0"
	.asciz	"dhr0"
	.asciz	"dhx0"
	.asciz	"dm0"
	.asciz	"dhr1"
	.asciz	"dhx1"
	.asciz	"dzr0"
	.asciz	"dzx0"
	.asciz	"dzr1"
	.asciz	"dzx1"
	.asciz	"dzr2"
	.asciz	"dzx2"
	.asciz	"dzr3"
	.asciz	"dzx3"
	.asciz	"dzr4"
	.asciz	"dzx4"
	.asciz	"dzr5"
	.asciz	"dzx5"
	.asciz	"dzr6"
	.asciz	"dzx6"
	.asciz	"dzr7"
	.asciz	"dzx7"
	.asciz	"ts0"
	.asciz	"dmfsr0"
	.asciz	"dmfsx0"
	.asciz	"dmfda0"
	.asciz	"dmfdb0"
	.asciz	"dmfr0"
	.asciz	"dmfx0"
	.asciz	"dmfl0"
	.asciz	"dmzra0"
	.asciz	"dmzxa0"
	.asciz	"dmzrb0"
	.asciz	"dmzxb0"
	.asciz	"dmzrc0"
	.asciz	"dmzxc0"
	.asciz	"dhur0"
	.asciz	"dhux0"
	.asciz	"lp0"
	.asciz	"qvk0"
	.asciz	"qvv0"
	.asciz	"qdd0"
	.asciz	"qda0"
	.asciz	"qdi0"
	.asciz	"ecr0"
	.asciz	"eccollide0"
	.asciz	"ecx0"
	.asciz	"de0"
	.asciz	"ilr0"
	.asciz	"ilc0"
	.asciz	"excd0"
	.asciz	"qe0"
_eintrnames:

	.globl	_intrcnt

	.globl	_eintrcnt
	.align 2
_intrcnt:
	.space	4 * 13
_fltintrcnt:
	.space	4 * 60
_eintrcnt:

	.text