+ .set HIGH,31 # mask for total disable
+ .set SZPT,4 # number of pages of user page table allocated per user
+ .set MCKVEC,4 # offset into Scbbase of machine check vector
+
+# Trap vectors and C interface for Vax
+
+#
+#
+#
+# System control block
+#
+
+ .set INTSTK,1 # handle this interrupt on the interrupt stack
+ .set HALT,3 # halt if this interrupt occurs
+ .align 9
+ .globl Scbbase
+Scbbase:
+ .long Xrandom + HALT # unused
+ .long Xmachcheck + HALT # machine check interrupt
+ .long Xkspnotval + HALT # kernal stack not valid
+ .long Xpowfail + HALT # power fail
+ .long Xprivinflt # privileged instruction
+ .long Xxfcflt # xfc instruction
+ .long Xresopflt # reserved operand
+ .long Xresadflt # reserved addressing
+ .long Xprotflt # protection
+ .long Xsegflt # segmentation
+ .long Xtracep # trace pending
+ .long Xbptflt # bpt instruction
+ .long Xrandom + HALT # compatibility mode fault
+ .long Xarithtrap # arithmetic trap
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xsyscall # chmk
+ .long Xchme+HALT # chme
+ .long Xchms+HALT # chms
+ .long Xchmu+HALT # chmu
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # software level 1
+ .long Xrandom + HALT # software level 2 (asts)
+ .long Xresched # reschedule nudge
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ubabase:
+ .long Xclockint + INTSTK # clock
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xconsrint + INTSTK # console receiver
+ .long Xconsxint + INTSTK # console transmitter
+
+# I/O vectors
+
+# IPL 14
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xua0int + INTSTK # UBA 0 br4
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+
+# IPL 15
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xua0int + INTSTK # UBA 0 br5
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xmba0int + INTSTK # mass bus adapter 0
+ .long Xmba1int + INTSTK # mass bus adapter 1
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+
+# IPL 16
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xua0int + INTSTK # UBA 0 br6
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+
+# IPL 17
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+ .long Xrandom + HALT # unused
+
+
+# 0x200
+# Produce a core image dump on mag tape
+ .globl doadump
+doadump:
+ movl sp,dumpstack # save stack pointer
+ movab dumpstack,sp # reinit sp
+ mfpr $PCBB,-(sp) # save u-area pointer
+ mfpr $MAPEN,-(sp) # save value
+ mfpr $IPL,-(sp) # ...
+ mtpr $0,$MAPEN # turn off memory mapping
+ mtpr $HIGH,$IPL # disable interrupts
+ pushr $0x3fff # save regs 0 - 13
+ calls $0,_dump # produce dump
+ halt
+
+ .data
+ .align 2
+ .space 58*4 # seperate stack for tape dumps
+ .globl dumpstack
+dumpstack:
+ .space 4
+ .text
+
+
+# I/O interrupt vector routines
+#
+
+# Catch random or unexpected interrupts
+
+ .align 2
+Xrandom:
+Xmachcheck:
+Xkspnotval:
+Xpowfail:
+Xchme:
+Xchms:
+Xchmu:
+ halt
+
+# Massbus 0 adapter interrupts
+
+ .align 2
+Xmba0int:
+ pushr $0x3f # save r0 - r5
+ movab MBA0_CSR,r0 # point at mba regs
+ movl MBA_AS(r0),r1 # get attn summary bits
+ cvtwl r1,-(sp) # push attn summary as arg
+ pushl MBA_SR(r0) # pass sr as argument
+ mnegl $1,MBA_SR(r0) # clear attention bit
+ calls $2,_hpintr # call rp06 interrupt dispatcher
+ brw int_ret # merge with common interrupt code
+
+
+# Massbus 1 adapter interrupts
+
+ .align 2
+Xmba1int:
+ pushr $0x3f
+ movab MBA1_CSR,r0
+ pushl MBA_AS(r0)
+ mnegl $1,MBA_AS(r0)
+ pushl MBA_SR(r0) # pass cr as argument_
+ mnegl $1,MBA_SR(r0) # clear attention bit
+ calls $2,_htintr # call te16 interrupt dispatcher
+ brw int_ret # return from interrupt
+
+
+# Unibus adapter interrupts
+
+ .align 2
+Xua0int: # UBA 0 interrupts
+ pushr $0x3f # save regs 0-5
+ pushab UBA0 # save UBA base addr
+ brb Xuacom # jump to common code
+Xua1int : # UBA 1 interrupts
+Xuacom : # common code for UBA interrupts
+ popr $1 # UBA base addr
+ mfpr $IPL,r2 # get br level
+ movl UBR_OFF-20*4(r0)[r2],r3 # get unibus device vector
+ bleq ubasrv # branch if zero vector or UBA service required
+# normal UBA interrupt point - device on a UBA has generated an
+# interrupt - r3 holds interrupt vector
+ubanorm :
+ movl _UNIvec(r3),r1 # get interrupt service routine address
+# and controller code from UNIBUS vector area
+ extzv $27,$4,r1,-(sp) # controller code is in 4 most
+# significant bits-1 of ISR addr
+ bicl2 $0x78000000,r1 # clear code
+ calls $1,(r1) # call ISR
+ brw int_ret # go to common interrupt return
+# here for zero or negative UBA interrupt vector.
+# negative vector -> UBA requires service
+ubasrv :
+ beql ubapass
+#
+# UBA service required
+# The following 'printf' calls should probably be replaced
+# with calls to an error logger and/or some corrective action.
+ bitl $CFGFLT,UCN_OFF(r0) # any SBI faults ?
+ beql UBAflt
+ pushab SBImsg
+ calls $1,_printf
+ halt
+#
+# no SBI fault bits set in UBA config reg - must be
+# some error bits set in UBA status reg
+UBAflt :
+ movl UST_OFF(r0),r2 # UBA status reg
+ pushr r2
+ pushab UBAmsg
+ calls $2,_printf
+ movl r2,UST_OFF(r0) # clear error bits
+ bicl2 $0x80000000,r1 # clear neg bit in vector
+ bneq ubanorm # branch if normal UBA interrupt to process
+ brb int_ret # restore regs and return
+#
+# zero interrupt vector - print message & continue
+ubapass :
+ pushab ZERmsg
+ calls $1,_printf
+ brb int_ret
+
+
+# Console receiver interrupt
+
+ .align 2
+Xconsrint:
+ pushr $0x3f # save registers 0 - 5
+ calls $0,_consrint
+ brb int_ret # merge
+
+
+# Console transmit interrupt
+ .align 2
+Xconsxint:
+ pushr $0x3f # save registers 0 - 5
+ calls $0,_consxint
+ brb int_ret
+
+
+# Clock interrupt
+ .align 2
+Xclockint:
+ pushr $0x3f # save regs 0 - 5
+ pushl 4+6*4(sp) # push psl
+ pushl 4+6*4(sp) # push pc
+ calls $2,_clock
+ brb int_ret
+
+
+#
+# Common code for interrupts
+# At this point, the interrupt stack looks like:
+#
+# ___________
+# | r0 | :isp
+# |-----------|
+# | ... |
+# |-----------|
+# | r13 |
+# |-----------|
+# | pc |
+# |-----------|
+# | psl |
+# |___________|
+
+
+int_ret:
+ bbssi $0,idleflag,int_r0 # set idle escape flag (no wait instr)
+int_r0:
+ popr $0x3f # restore regs 0 - 5
+ bitl $PSL_CURMOD,4(sp) # interrupt from user mode?
+ beql int_r1 # no, from kernal, just rei
+ tstb _runrun # should we reschedule?
+ beql int_r1 # no, just rei
+#
+# If here, interrupt from user mode, and time to reschedule.
+# to do this, we set a software level 3 interrupt to
+# change to kernal mode, switch stacks,
+# and format kernal stack for a `qswitch' trap to force
+# a reschedule.
+#
+ mtpr $3,$SIRR # request level 1 software interrupt
+int_r1:
+ rei # return to interrupted process
+
+#
+# Trap and fault vector routines
+#
+
+# Reschedule trap (Software level 3 interrupt)
+ .align 2
+Xresched:
+ movpsl -(sp) # get ps
+ bicl2 $PSL_IPL,(sp) # lower ipl
+ pushab resc1 # push pc
+ rei # lower ipl, jump to resc1
+
+resc1:
+ pushl $0 # dummy code
+ pushl $RESCHED # type
+ brb alltraps # merge
+
+
+# privileged instruction fault
+ .align 2
+Xprivinflt:
+ pushl $0 # push dummy code
+ pushl $PRIVINFLT # push type
+ brb alltraps # merge
+
+
+
+# xfc instruction fault
+ .align 2
+Xxfcflt:
+ pushl $0 # push dummy code value
+ pushl $XFCFLT # push type value
+ brb alltraps # merge
+
+
+# reserved operand fault
+ .align 2
+Xresopflt:
+ pushl $0 # push dummy code value
+ pushl $RESOPFLT # push type value
+ brb alltraps # merge
+
+
+# reserved addressing mode fault
+ .align 2
+Xresadflt:
+ pushl $0 # push dummy code value
+ pushl $RESADFLT # push type value
+ brb alltraps # merge with common code
+
+
+# bpt instruction fault
+ .align 2
+Xbptflt:
+ pushl $0 # push dummy code value
+ pushl $BPTFLT # push type value
+ brb alltraps # merge with common code
+
+# Trace trap
+
+ .align 2
+Xtracep:
+ pushl $0 # push dummy code value
+ pushl $TRCTRAP # push type value
+ brb alltraps # go do it
+
+# Arithmitic trap
+ .align 2
+Xarithtrap:
+ pushl $ARITHTRAP # push type value
+ brb alltraps # merge with common code
+
+
+# Protection fault
+
+ .align 2
+Xprotflt:
+ blbs (sp),Xsegflt # check for pt length violation
+ addl2 $4,sp # pop fault param word
+ pushl $PROTFLT
+ brb alltraps
+
+# Segmentation fault
+
+ .align 2
+Xsegflt:
+ addl2 $4,sp
+ pushl $SEGFLT
+ brb alltraps
+
+
+
+
+#
+# CHMK trap (syscall trap)
+# on entry, kernal stack:
+#
+# ___________
+# | code | :ksp
+# |-----------|
+# | pc |
+# |-----------|
+# | psl |
+# |___________|
+#
+#
+#
+# stack (parameters) at calls to _trap:
+#
+# ___________
+# | ap | :ksp
+# |-----------|
+# | r0 |
+# |-----------|
+# | ... |
+# |-----------|
+# | r13 |
+# |-----------|
+# | usp |
+# |-----------|
+# | type |
+# |-----------|
+# | code |
+# |-----------|
+# | pc |
+# |-----------|
+# | psl |
+# |___________|
+#
+
+ .align 2
+Xsyscall:
+ pushl $SYSCALL # push type value
+alltraps:
+ movq 8(sp),_u+PCB_PC # save pc
+ bitl $PSL_CURMOD,12(sp) # from user mode?
+ beql sysc1 # no
+# Prepare arguments to _trap, note that type has already been pushed
+ mfpr $USP,-(sp) # get usp
+ pushr $0x3fff # registers 0 - 13
+ pushl ap # ptr to syscall parameters
+#
+# Call _trap with wrong number of arguments
+# so args not popped by ret
+#
+ calls $1,_trap
+# Restore
+ popr $0x3fff # restore regs 0 - 13
+ mtpr (sp)+,$USP # restore usp
+ addl2 $8,sp # pop type, code
+#
+ bitl $PSL_CURMOD,4(sp) # are we returning to user mode?
+ beql sysc2 # no
+# Return
+ rei
+
+sysc1:
+ movab emsg1,eptr # set message pointer
+ brb err_print # print message and halt
+
+sysc2:
+ movab emsg2,eptr # pointer to error message
+ brb err_print # print msg and halt
+
+#
+# err_print
+# print message on console and die
+# message pointed to by eptr, terminated by zero byte.
+#
+
+err_print:
+ mtpr $HIGH,$IPL # disable all interrupts
+ mtpr $0,$TXCS # disable interrupts on console transmitter
+eloop1:
+ mfpr $TXCS,ewk1 # get transmitter status
+ bbc $TXCS_BRDY,ewk1,eloop1 # loop if not ready to transmit
+ tstb *eptr # end of message?
+ beql eout # yes, out of loop
+ movzbl *eptr,ewk1 # get byte of message
+ incl eptr # bump pointer
+ mtpr ewk1,$TXDB # give byte to transmitter
+ brb eloop1 # loop
+
+eout:
+ halt
+
+ .data
+eptr: .long 0
+ewk1: .long 0
+ .text
+
+
+
+#
+# Initialization
+
+#
+# IPL == 1F
+# MAPEN == off
+# SCBB, PCBB not set
+# SBR, SLR not set
+# ISP, KSP not set
+#
+ .globl start
+start:
+ .word 0x0000
+ mtpr $HIGH,$IPL # no interrupts yet
+ mtpr $Scbbase,$SCBB # set SCBB
+ mtpr $_Sysmap,$SBR # set SBR
+ mtpr $Syssize,$SLR # set SLR
+ mtpr $_Sysmap,$P0BR # set temp P0BR
+ mtpr $Syssize,$P0LR # set temp P0LR
+ movl $_intstack+2048,sp # set ISP
+# initialize i/o adatpers
+ movl $1,PHYSMBA0+4 # init & interrupt enable
+ movl $4,PHYSMBA0+4 # init & interrupt enable
+ movl $1,PHYSMBA1+4 # init interrupt enable
+ movl $4,PHYSMBA1+4 # init interrupt enable
+ movl $1,PHYSUBA+4 # init interrupt enable
+ movl $0x78,PHYSUBA+4 # init interrupt enable
+
+ movl Scbbase+MCKVEC,r5 # save machine check entry
+ movab startint+INTSTK,Scbbase+MCKVEC # set new vector address
+#
+# will now see how much memory there really is
+# in 64kb chunks, save number of bytes in r7
+#
+ mtpr $HIGH-1,$IPL # allow machine check interrupts
+ clrl r7
+startlp:
+ tstl (r7) # this chunk really there?
+ acbl $8096*1024-1,$64*1024,r7,startlp # loop till machine check
+ brb startint # full load of memory, avoid .align
+ .align 2
+startint:
+ mtpr $0,$SBIFS # clear sbi fault status
+ movl r5,Scbbase+MCKVEC # restore machine check vector
+ movl $_intstack+2048,sp # reset interrupt stack pointer
+
+# clear memory starting with unitialized data (kernal)
+ movab _edata,r6
+ movab _end+8096,r5 # clear uninitialized data and some slop
+strtclr:
+ clrq (r6)
+ acbl r5,$8,r6,strtclr
+
+#
+# initialize system page table
+#
+ movab _etext+511,r1 # end of kernal text segment
+ bbcc $31,r1,strt1 # turn off high order bit
+strt1:
+ ashl $-9,r1,r1 # last page of kernal text
+ clrl r2 # point at first kernal text page
+strtlp1:
+ bisl3 $PG_V|PG_KR,r2,_Sysmap[r2] # initialize page table entry
+ aoblss r1,r2,strtlp1 # fill text entries
+ movab _end+511,r1 # end of kernal data segment
+ bbcc $31,r1,strt2 # turn off high order bit
+strt2:
+ ashl $-9,r1,r1 # last page of kernal data
+strtlp2:
+ bisl3 $PG_V|PG_KW,r2,_Sysmap[r2] # fill data entries
+ aoblss r1,r2,strtlp2
+
+# init i/o space page table entries
+ movl $PHYSUBA/512,r1 # page frame number for uba
+ movab _Sysmap+uba_offset,r2 # page table address
+ movab 15(r1),r3 # last pt entry
+strtlp3:
+ bisl3 $PG_V|PG_KW,r1,(r2)+ # init pt entry
+ aobleq r3,r1,strtlp3
+ movl $PHYSUMEM/512,r1
+ movab _Sysmap+umem_offset,r2 # page table address
+ movab 15(r1),r3 # limit
+strtlp4:
+ bisl3 $PG_V|PG_KW,r1,(r2)+
+ aobleq r3,r1,strtlp4
+ movl $PHYSMBA0/512,r1
+ movab _Sysmap+mba0_offset,r2
+ movab 15(r1),r3
+strtlp5:
+ bisl3 $PG_V|PG_KW,r1,(r2)+
+ aobleq r3,r1,strtlp5
+ movl $PHYSMBA1/512,r1
+ movab _Sysmap+mba1_offset,r2
+ movab 15(r1),r3
+strtlp6:
+ bisl3 $PG_V|PG_KW,r1,(r2)+
+ aobleq r3,r1,strtlp6
+
+ mtpr $1,$TBIA # invalidate all trans buffer entries
+ mtpr $1,$MAPEN # turn on memory mapping
+ jmp *$startmap # put system virtual address in pc
+
+startmap:
+# set maxmem = btoc(r7)
+ ashl $-9,r7,_maxmem
+
+#
+# Setup context for proc[0] == Scheduler
+#
+# address first page past _end
+# this will be u area for proc[0].
+# initialize u area page table entries.
+# initialize (slightly) the pcb.
+
+ movab _end+511,r6
+ bicl2 $0x1ff,r6 # make page boundary
+
+# set up u area page table
+ bbcc $31,r6,strt3
+strt3:
+ ashl $-9,r6,r3 # r3 = btoc(r6)
+ bisl3 $PG_V|PG_KW,r3,_Sysmap+u_ptoffset # init first u pt entry
+ movab _u,r1 # point at _u area
+ mtpr r1,$TBIS
+ movab usize*512(r1),PCB_KSP(r1) # init ksp
+ mnegl $1,PCB_ESP(r1) # invalidate esp
+ mnegl $1,PCB_SSP(r1) # invalidate ssp
+ movl $0x80000000,PCB_USP(r1) # set user sp
+ movab _u+usize*512,PCB_P0BR(r1) # p0 page table pointer
+ clrl PCB_P0LR(r1) # size zero page table
+ movb $4,PCB_P0LR+3(r1) # disable ast
+ movab _u+(usize+SZPT)*512-0x800000,PCB_P1BR(r1) # p1 page table pointer
+ movl $0x200000,PCB_P1LR(r1) # invalid p1 p t length
+ movl $SZPT,PCB_SZPT(r1) # init number pages usr page table
+ ashl $-9,r6,-(sp) # push arg for setupu
+ pushl $1 # ditto
+ movl sp,ap # set up arg pointer
+ bsbw setupu
+ addl2 $8,sp # pop stack
+
+ mtpr r6,$PCBB # first pcb
+
+ ldpctx # set regs, p0br, p0lr, p1br, p1lr,
+# astlvl, ksp, and change to kernal mode
+ addl2 $8,sp # pop dummy pc, psl
+ mtpr $0,$IPL # enable interrupts
+ movab _end+511,r0 # calculate firstaddr
+ bbcc $31,r0,strt4
+strt4:
+ ashl $-9,r0,-(sp) # convert to clicks and stack
+ calls $1,_main # startup, fork off /etc/init
+#
+# proc[1] == /etc/init now running here.
+# execute code at location 0, in user mode.
+#
+ pushl $PSL_CURMOD|PSL_PRVMOD # psl, user mode, ipl= 0
+ pushl $0 # pc, $location 0
+ rei # do /etc/init
+
+
+#
+# Primitives
+#
+
+_display: .globl _display
+_savfp: .globl _savfp
+_restfp: .globl _restfp
+ .word 0x0000
+ ret
+
+_addupc: .globl _addupc
+ .word 0x0000
+ movl 8(ap),r2 # &u.u_prof
+ subl3 8(r2),4(ap),r0 # corrected pc
+ blss addret
+ extzv $1,$31,r0,r0 # logical right shift
+ extzv $1,$31,12(r2),r1 # ditto for scale
+ mull2 r1,r0
+ ashl $-14,r0,r0
+ incl r0
+ bicb2 $1,r0
+ cmpl r0,4(r2) # length
+ bgequ addret
+ addl2 (r2),r0 # base
+ probew $3,$2,(r0)
+ beql adderr
+ addw2 12(ap),(r0)
+addret:
+ ret
+adderr:
+ clrl 12(r2)
+ ret
+
+
+_fubyte: .globl _fubyte
+_fuibyte:.globl _fuibyte
+ .word 0x0000
+ prober $3,$1,*4(ap) # byte accessible ?
+ beql eret # no
+ movzbl *4(ap),r0
+ ret
+
+_subyte: .globl _subyte
+_suibyte:.globl _suibyte
+ .word 0x0000
+ probew $3,$1,*4(ap) # byte accessible ?
+ beql eret # no
+ movb 8(ap),*4(ap)
+ clrl r0
+ ret
+
+_fuword: .globl _fuword
+_fuiword:.globl _fuiword
+ .word 0x0000
+ prober $3,$4,*4(ap)
+ beql eret
+ movl *4(ap),r0
+ ret
+
+_suword: .globl _suword
+_suiword:.globl _suiword
+ .word 0x0000
+ probew $3,$4,*4(ap)
+ beql eret
+ movl 8(ap),*4(ap)
+ clrl r0
+ ret
+eret:
+ mnegl $1,r0 # error return
+ ret
+
+_copyin: .globl _copyin
+_copyiin:.globl _copyiin
+ .word 0x0000
+ movl 12(ap),r0 # copy length
+ movl 4(ap),r1 # copy user address
+ cmpl $512,r0 # probing one page or less ?
+ bgeq cishort # yes
+ciloop:
+ prober $3,$512,(r1) # bytes accessible ?
+ beql eret # no
+ addl2 $512,r1 # incr user address ptr
+ acbl $513,$-512,r0,ciloop # reduce count and loop
+cishort:
+ prober $3,r0,(r1) # bytes accessible ?
+ beql eret # no
+ movc3 12(ap),*4(ap),*8(ap)
+ clrl r0
+ ret
+
+_copyout: .globl _copyout
+_copyiout:.globl _copyiout
+ .word 0x0000
+ movl 12(ap),r0 # get count
+ movl 8(ap),r1 # get user address
+ cmpl $512,r0 # can do in one probew?
+ bgeq coshort # yes
+coloop:
+ probew $3,$512,(r1) # bytes accessible?
+ beql eret # no
+ addl2 $512,r1 # increment user address
+ acbl $513,$-512,r0,coloop # reduce count and loop
+coshort:
+ probew $3,r0,(r1) # bytes accessible?
+ beql eret # no
+ movc3 12(ap),*4(ap),*8(ap)
+ clrl r0
+ ret
+
+_idle: .globl _idle
+ .word 0x0000
+ mtpr $0,$IPL # enable interrupts
+waitloc: blbc idleflag,waitloc # loop until interrupt
+ewaitloc: bbcci $0,idleflag,idle1 # clear idle escape flag
+idle1:
+ ret
+ .data
+ .globl _waitloc
+ .globl _ewaitloc
+ .align 2
+_waitloc: .long waitloc
+_ewaitloc: .long ewaitloc
+idleflag: .long 0
+ .text
+
+
+# save reg's and ret loc into save area - return 0
+ .globl _save
+_save : # save(save_area)
+ .word 0x0
+ mtpr $HIGH,$IPL
+ movl 4(ap),r0 # save area addr
+ movab 2*4(ap),sp # restore stack to val before 'save' call
+ movl 8(fp),ap # restore ap " " "
+ movl 16(fp),r1 # restore pc " " "
+ movl 12(fp),fp # restore fp " " "
+ movq r6,(r0)+
+ movq r8,(r0)+
+ movq r10,(r0)+
+ movq ap,(r0)+ # ap & fp
+ movl sp,(r0)+
+ movl r1,(r0)+ # ret loc of call to 'save'
+ movpsl -(sp)
+ pushl r1
+ svpctx # save reg's -> PCB
+ movpsl -(sp) # set up for return
+ bicl2 $PSL_IS|PSL_IPL,(sp) # undo SVPCTX
+ pushl r1 # ret loc
+ clrl r0 # return val
+ rei
+#
+#
+# switch to another process's '_u' area - return val 1
+ .globl _resume
+_resume : # resume(proc_addr,save_addr)
+ .word 0x0
+ mtpr $HIGH,$IPL # inhibit interrupts
+ ashl $9,4(ap),r5 # proc byte addr
+ # area of proc argument
+ movl 8(ap),retloc
+ bsbw setupu # set up '_sysmap' PTE's to map into '_u'
+ movl _u,sp # KSP from u-area
+ mtpr r5,$PCBB
+ ldpctx
+ addl2 $8,sp # clear ps,pc from stack
+ movl retloc,r1 # 'ssav' or 'qsav' addr
+ movq (r1)+,r6
+ movq (r1)+,r8
+ movq (r1)+,r10
+ movq (r1)+,ap
+ movl (r1)+,sp
+ movl $1,r0 # return val
+ mtpr $0,$IPL
+ jmp *(r1)+ # return to caller at 'save' address
+#
+ .data
+ .align 2
+retloc: .space 1*4
+ .text
+
+
+# initialize u area page table entries
+
+setupu:
+ movl (sp)+,r0 # get return pc
+ addl3 $PG_V|PG_KW,4(ap),r1 # first pt entry of user area
+ movab usize(r1),r2 # one past last pt entry of user
+ movab _Sysmap+u_ptoffset,r3 # addr for 1st user pt entry
+ movab _u,r4
+ mtpr r4,$TBIS # invalidate old trans buffer entry
+ movl r1,(r3)+ # store page table entry
+ addl2 _u+PCB_SZPT,r2 # add on size of user page table
+ brb setulp1
+setulp:
+ mtpr r4,$TBIS # ivalidate page table entry
+ movl r1,(r3)+ # store page table entry
+setulp1:
+ addl2 $512,r4
+ aoblss r2,r1,setulp # -> till done
+ jmp (r0) # funny return in case of changing stacks
+
+
+# disable interrupts
+_spl1: .globl _spl1
+ .word 0x0000
+ mfpr $IPL,r0 # get IPL value
+ mtpr $2,$IPL # disable RESCHED & AST interrupts
+ ret
+
+_spl4: .globl _spl4
+ .word 0x0000
+ mfpr $IPL,r0
+ mtpr $0x14,$IPL # disable bus level 4 interrupts
+ ret
+
+_spl5: .globl _spl5
+ .word 0x0000
+ mfpr $IPL,r0
+ mtpr $0x15,$IPL # disable bus level 5 interrupts
+ ret
+
+_spl6: .globl _spl6
+_spl7: .globl _spl7
+ .word 0x0000
+ mfpr $IPL,r0
+ mtpr $0x18,$IPL # disable bus level 7 and clock interrupts
+ ret
+
+# enable interrupts
+_spl0: .globl _spl0
+ .word 0x0000
+ mfpr $IPL,r0
+ mtpr $0,$IPL
+ ret
+
+# restore interrupt state
+_splx: .globl _splx
+ .word 0x0000
+ mfpr $IPL,r0
+ mtpr 4(ap),$IPL
+ ret
+
+#
+# Copy 1 relocation unit (512 bytes)
+# from one physical address to another
+_copyseg: .globl _copyseg
+ .word 0x0000
+ mfpr $IPL,r0 # get current pri level
+ mtpr $HIGH,$IPL # turn off interrupts
+ bisl3 $PG_V|PG_KR,4(ap),_Sysmap+CMAP1
+ bisl3 $PG_V|PG_KW,8(ap),_Sysmap+CMAP2
+ mtpr $CADDR1,$TBIS # invalidate entry for copy
+ mtpr $CADDR2,$TBIS
+ movc3 $512,CADDR1,CADDR2
+ mtpr r0,$IPL # restore pri level
+ ret
+
+# zero out physical memory
+# specified in relocation units (512 bytes)
+_clearseg: .globl _clearseg
+ .word 0x0000
+ mfpr $IPL,r0 # get current pri level
+ mtpr $HIGH,$IPL # extreme pri level
+ bisl3 $PG_V|PG_KW,4(ap),_Sysmap+CMAP1
+ mtpr $CADDR1,$TBIS
+ movc5 $0,(r0),$0,$512,CADDR1
+ mtpr r0,$IPL # restore pri level
+ ret
+
+# Check address
+# given virtual address, byte count, and rw flag
+# returns 0 on no access
+_useracc: .globl _useracc
+ .word 0x0000
+ movl 4(ap),r0 # get va
+ movl 8(ap),r1 # count
+ tstl 12(ap) # test for read access ?
+ bneq userar # yes
+ cmpl $512,r1 # can we do it in one probe ?
+ bgeq uaw2 # yes
+uaw1:
+ probew $3,$512,(r0)
+ beql uaerr # no access
+ addl2 $512,r0
+ acbl $513,$-512,r1,uaw1
+uaw2:
+ probew $3,r1,(r0)
+ beql uaerr
+ movl $1,r0
+ ret
+
+userar:
+ cmpl $512,r1
+ bgeq uar2
+uar1:
+ prober $3,$512,(r0)
+ beql uaerr
+ addl2 $512,r0
+ acbl $513,$-512,r1,uar1
+uar2:
+ prober $3,r1,(r0)
+ beql uaerr
+ movl $1,r0
+ ret
+
+uaerr:
+ clrl r0
+ ret
+
+# kernacc
+# check for kernal access privileges
+#
+
+ .globl _kernacc
+_kernacc:
+ .word 0x0000
+
+ movl 4(ap),r0 # virtual address
+ bbcc $31,r0,kacc1
+ mfpr $SBR,r2 # address and length of page table (system)
+ 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
+ ashl $-9,r0,r0 # page number
+ ashl $-9,r1,r1
+ 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
+ bgeq kacerr # address too high
+kacc4:
+ movl (r2)[r0],r1
+ bbc $31,r1,kacerr # valid bit is off
+ cmpzv $27,$4,r1,$1 # check protection code
+ bleq kacerr # no access allowed
+ tstb 12(ap)
+ bneq kacc5 # only check read access
+ cmpzv $27,$2,r1,$3 # check low 2 bits of prot code
+ beql kacerr # no write access
+kacc5:
+ aobleq r1,r0,kacc4 # next page
+ movl $1,r0 # no errors
+ ret
+kacerr:
+ clrl r0 # error
+ ret
+
+# calculate physical address of user virtual address
+_realaddr: .globl _realaddr
+ .word 0x0000
+ movl 4(ap),r0 # virtual address
+ blss raerr # we don't map kernal virtual addresses
+ bbsc $30,r0,rasseg # stack segment address
+ mfpr $P0BR,r1
+ mfpr $P0LR,r2
+ ashl $-9,r0,r3 # get page number
+ cmpl r3,r2 # valid page number?
+ bgeq raerr # no
+ra1:
+ movl (r1)[r3],r4 # get page table entry
+ bbc $31,r4,raerr # valid bit off - error
+ ashl $9,r4,r5 # construct physical address
+ extzv $0,$9,r0,r0 # offset within page
+ bisl2 r5,r0 # final physical address
+ ret
+rasseg:
+ mfpr $P1BR,r1
+ mfpr $P1LR,r2
+ ashl $-9,r0,r3
+ cmpl r3,r2
+ bgeq ra1
+raerr:
+ clrl r0
+ ret
+
+#
+# unsigned int divide :
+# (int) i = udiv( (int)dvdnd , (int) divis)
+#
+# unsigned int remainder :
+# (int) j = urem( (int)dvdnd , (int) divis)
+#
+ .text
+ .align 1
+ .globl _udiv
+ .globl _urem
+#
+_udiv :
+ .word 0 # no reg save
+ movl 4(ap),r0 # dividend
+ clrl r1
+ ediv 8(ap),r0,r0,r1 # quotient in r0
+ ret
+#
+ .align 1
+_urem :
+ .word 0
+ movl 4(ap),r0
+ clrl r1
+ ediv 8(ap),r0,r1,r0 # remainder in r0
+ ret
+# define user area virtual address
+ .set physpages,1024
+ .set kernsize,256 # number of page table entries allocated to kernal
+ .globl _u
+ .set usize,4 # size of user area, in pages
+ .set _u,0x80000000 + kernsize*512
+ .set u_ptoffset,256*4 # offset into _Sysmap of ptentries of _u
+ .set CMAP1,u_ptoffset + 16*4 # offset into _Sysmap of 1st seg copy entry
+ .set CMAP2,CMAP1+4 # ditto 2ed entry
+ .set CADDR1,_u + 16*512 # virtual address of 1st copy segment
+ .set CADDR2,CADDR1+512 # ditto second segment
+ .set PHYSUBA,0x20006000 # real address of uba
+ .set PHYSMBA0,0x20010000 # real addr of mba 0
+ .set PHYSMBA1,0x20012000 # real addre of mba1
+ .set PHYSUMEM,0x2013e000 # real address of unibus memory
+ .set uba_offset,CMAP1+16*4 # offset in Sysmap of uba entries
+ .set umem_offset,uba_offset+16*4 # ... unibus device registers
+ .set mba0_offset,umem_offset+16*4 # ... massbus 0
+ .set mba1_offset,mba0_offset+16*4 # ... massbus 1
+ .set mba2_offset,mba1_offset+16*4 # ... massbus 2
+ .set mba3_offset,mba2_offset+16*4 # ... massbus 3
+
+ .set qsoff,0x140 # offset to 'qsav' pcb in 'u' area
+ .set ssoff,360 #offset to "ssav' in u_area
+
+
+#
+# Error messages
+#
+ .data
+
+emsg1:
+ .byte 0xa,0xa,0xa,0xd,0x54,0x52,0x41,0x50,0x20
+ .byte 0x46,0x52,0x4f,0x4d,0x20
+ .byte 0x4b,0x45,0x52,0x4e,0x41,0x4c,0x20
+ .byte 0x4d,0x4f,0x44,0x45,0xa,0xa,0xd,0x0
+
+emsg2:
+ .byte 0xa,0xa,0xa,0xd,0x54,0x52,0x41,0x50,0x20
+ .byte 0x52,0x45,0x54,0x55,0x52,0x4e,0x20
+ .byte 0x44,0x4f,0x20
+ .byte 0x4b,0x45,0x52,0x4e,0x41,0x4c,0x20
+ .byte 0x4d,0x4f,0x44,0x45,0xa,0xa,0xd,0x0
+
+SBImsg :
+ .byte 'S,'B,'I,' ,'f,'a,'u,'l,'t,' ,012,0
+
+UBAmsg :
+ .byte 'U,'B,'A,' ,'e,'r,'r,'o,'r,' ,'%,'x,012,0
+
+ZERmsg :
+ .byte 'Z,'e,'r,'o,' ,'V,'e,'c,'t,'o,'r,012,0
+
+#
+# _Sysmap:
+# system page table
+#
+# structure:
+# 2 pages of page table entries
+# reserved for kernal text and data.
+# 1 additional page of page table entries
+# used in mapping the u area (16 entries),
+# utility entries (16 entries),
+# unibus adapter (16 entries),
+# unibus device memory (16 entries),
+# massbus adapter 0 (16 entries),
+# massbus adapter 1 (16 entries),
+# massbus adapter 2 (16 entries),
+# massbus adapter 3 (16 entries).
+#
+#
+
+ .align 2
+ .globl _Sysmap
+_Sysmap:
+ .space 3*128*4 # 3 pages of page table entries for kernal
+ .set Syssize,3*128 # number pt entries in sys page table