# Machine Language Assist for UC Berkeley Virtual Vax/Unix
.set HIGH,31 # mask for total disable
.set MCKVEC,4 # offset into Scbbase of machine check vector
.set UPAGES,6 # size of user area, in pages
# ====================================
# Trap vectors and C interface for Vax
# ====================================
.set INTSTK,1 # handle this interrupt on the interrupt stack
.set HALT,3 # halt if this interrupt occurs
.long Xstray + INTSTK # unused
.long Xmachcheck + HALT # machine check interrupt
.long Xkspnotval + HALT # kernel 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 and pt length violation
.long Xtransflt # address translation not valid fault
.long Xtracep # trace pending
.long Xbptflt # bpt instruction
.long Xcompatflt # compatibility mode fault
.long Xarithtrap # arithmetic trap
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # software level 1
.long Xstray + INTSTK # software level 2 (asts)
.long Xresched # reschedule nudge
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xcnrint + INTSTK # console receiver
.long Xcnxint + INTSTK # console transmitter
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xua0int + INTSTK # UBA 0 br4
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xua0int + INTSTK # UBA 0 br5
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xmba0int + INTSTK # mass bus adapter 0
.long Xmba1int + INTSTK # mass bus adapter 1
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xua0int + INTSTK # UBA 0 br6
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
.long Xstray + INTSTK # unused
# =====================================
# Produce a core image dump on mag tape
# =====================================
movl sp,dumpstack # save stack pointer
movab dumpstack,sp # reinit stack
mfpr $PCBB,-(sp) # save u-area pointer
mfpr $MAPEN,-(sp) # save value
mtpr $0,$MAPEN # turn off memory mapping
mtpr $HIGH,$IPL # disable interrupts
pushr $0x3fff # save regs 0 - 13
calls $0,_dump # produce dump
.space 58*4 # separate stack for tape dumps
# Debugging print switches given here so they won't move around
# =============================
# I/O interrupt vector routines
# =============================
.set PHYSMCR,0x20002000 # memory controller register
.set PHYSUBA,0x20006000 # uba 0
.set PHYSMBA0,0x20010000 # mba 0
.set PHYSMBA1,0x20012000 # mba 1
.set PHYSUMEM,0x2013e000 # unibus memory
# Catch random or unexpected interrupts
# Massbus 0 adapter interrupts
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
pushl MBA_SR(r0) # pass sr 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
pushr $0x3f # save regs 0-5
mfpr $IPL,r2 # get br level
movl UBA0+UBR_OFF-20*4[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. Get the service routine
# address and controller code from the UNIBUS vector area
# and service the interrupt.
extzv $27,$4,r1,r0 # controller code is in 4 most
# significant bits-1 of ISR addr
bicl2 $0x78000000,r1 # clear code
jlbc r1,ubanpdma # no pseudo dma here
jmp -1(r1) # branch to pseudo dma rtn
pushl r0 # controller code
brw int_ret # go to common interrupt return
# Come here for zero or negative UBA interrupt vector.
# Negative vector -> UBA requires service.
# The following 'printf' calls should probably be replaced
# with calls to an error logger and/or some corrective action.
bitl $CFGFLT,UBA0+UCN_OFF # any SBI faults ?
pushr $0xf # save regs 0-3
# No SBI fault bits set in UBA config reg - must be
# some error bits set in UBA status reg.
movl UBA0+UST_OFF,r2 # UBA status reg
pushr $0xf # save regs 0-3
movl r2,UBA0+UST_OFF # clear error bits
bicl2 $0x80000000,r3 # clear neg bit in vector
jneq ubanorm # branch if normal UBA interrupt
brw int_ret # restore regs and return
# Zero interrupt vector - count 'em
# bisw2 $4,*_draddr # leading edge for dr11-c
movab _dzpdma(r0),r3 # pdma structure base
movl (r0)+,r1 # device register address
movzbl 1(r1),r2 # get line number
incl _dzdcnt ## loop trips
bicb2 $0xf8,r2 # clear garbage bits
addl2 r2,r0 # point at line's pdma structure
cmpl r2,(r0)+ # p_mem < p_end ?
bgequ dzpcall # no, go call dzxint
movb (r2)+,6(r1) # dztbuf = *p_mem++
brb dzploop # check for another line
# bicw2 $4,*_draddr # trailing edge for dr11-c
pushl (r0) # push tty address
calls $1,_dzxint # call interrupt rtn
brb dzploop # check for another line
# Console receiver interrupt
pushr $0x3f # save registers 0 - 5
# Console transmit interrupt
pushr $0x3f # save registers 0 - 5
pushr $0x3f # save regs 0 - 5
pushl 4+6*4(sp) # push psl
pushl 4+6*4(sp) # push pc
# Common code for interrupts.
# At this point, the interrupt stack looks like:
# bbssi $0,idleflag,int_r0 # escape from idle() if old switch code
popr $0x3f # restore regs 0 - 5
bitl $PSL_CURMOD,4(sp) # interrupt from user mode?
beql int_r1 # no, from kernel, 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 kernel mode, switch stacks, and format
# kernel stack for a `qswitch' trap to force a reschedule.
mtpr $3,$SIRR # request level 1 software interrupt
rei # return to interrupted process
# ==================================
# User area virtual addresses
# ==================================
.set _u,0x80000000 - UPAGES*NBPG
.set _umbabeg,((UBA0map-_Sysmap)/4)*512+0x80000000
.set _umbaend,((umend-_Sysmap)/4)*512+0x80000000
.set _usrpt,((_Usrptmap-_Sysmap)/4)*NBPG+0x80000000
.set _forkutl,((_Forkmap-_Sysmap)/4)*NBPG+0x80000000
.set _xswaputl,((_Xswapmap-_Sysmap)/4)*NBPG+0x80000000
.set _xswap2utl,((_Xswap2map-_Sysmap)/4)*NBPG+0x80000000
.set _swaputl,((_Swapmap-_Sysmap)/4)*NBPG+0x80000000
.set _pushutl,((_Pushmap-_Sysmap)/4)*NBPG+0x80000000
.set _vfutl,((_Vfmap-_Sysmap)/4)*NBPG+0x80000000
.set CADDR1,((CMAP1-_Sysmap)/4)*NBPG+0x80000000
.set CADDR2,((CMAP2-_Sysmap)/4)*NBPG+0x80000000
.set _mcr,((_mcrmap-_Sysmap)/4)*NBPG+0x80000000
.set _vmmap,((_mmap-_Sysmap)/4)*NBPG+0x80000000
.set Syssize,(eSysmap-_Sysmap)/4
# ==============================
# Trap and fault vector routines
# ==============================
# Reschedule trap (Software level 3 interrupt)
# Privileged instruction fault
pushl $0 # push dummy code
pushl $PRIVINFLT # push type
pushl $0 # push dummy code value
pushl $XFCFLT # push type value
pushl $0 # push dummy code value
pushl $RESOPFLT # push type value
# Reserved addressing mode fault
pushl $0 # push dummy code value
pushl $RESADFLT # push type value
brw alltraps # merge with common code
pushl $0 # push dummy code value
pushl $BPTFLT # push type value
brw alltraps # merge with common code
# Compatibility mode fault
pushl $COMPATFLT # push type value
brw alltraps # merge with common code
pushl $0 # push dummy code value
pushl $TRCTRAP # push type value
pushl $ARITHTRAP # push type value
brw alltraps # merge with common code
# Protection and segmentation fault
blbs (sp),segflt # check for pt length violation
addl2 $4,sp # pop fault param word
# Translation Not Valid Fault
bbs $1,(sp),tableflt # check for page table fault
addl2 $4,sp # pop fault parameter word
pushl $PAGEFLT # push type value
addl2 $4,sp # pop fault parameter word
pushl $TABLEFLT # push type value
# all traps but syscalls...
mfpr $USP,-(sp) # get usp
calls $0,_trap # $0 so ret wont pop args
mtpr (sp)+,$USP # restore usp
addl2 $8,sp # pop type, code
mtpr $HIGH,$IPL # make sure we are not going to
# CHMK trap (syscall trap)
# Stack (parameters) at calls to _trap or _syscall
pushl $SYSCALL # push type value
mfpr $USP,-(sp) # get usp
calls $0,_syscall # $0 so ret wont pop args
mtpr (sp)+,$USP # restore usp
addl2 $8,sp # pop type, code
mtpr $HIGH,$IPL # make sure we are not going to
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 adapters.
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
tstl (r7) # this chunk really there?
acbl $8096*1024-1,$64*1024,r7,startlp # loop till mach check
brb startint # full load of memory
mtpr $0,$SBIFS # clear sbi fault status
movl r5,Scbbase+MCKVEC # restore machine check vector
movl $_intstack+2048,sp # reset interrupt stack pointer
# calculate size of cmap[] based on available memory, and allocate space for it
divl2 $(NBPG*CLSIZE)+CMSIZE,r1
# Clear memory starting with kernel bss, and extra pages for
# proc 0 u. and proc 0 paget.
movab _ecmap,r5 # clear to end of cmap[]
addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5
# Finagle _trap and _syscall to save r0-r11 so
# that it won't be necessary to pushr/popr what
# the (already time consuming) calls is prepared to do.
# The fact that this is done is well known (e.g. in the definition
# of the stack offsets of the registers in ../h/reg.h)
bisw2 $0x0fff,_trap # so _trap saves r0-r11
bisw2 $0x0fff,_syscall # so _syscall saves r0-r11
# Initialize system page table
movab _etext+NBPG-1,r1 # end of kernel text segment
bbcc $31,r1,strt1 # turn off high order bit
ashl $-9,r1,r1 # last page of kernel text
clrl r2 # point at first kernel text page
bisl3 $PG_V|PG_KR,r2,_Sysmap[r2] # initialize page table entry
aoblss r1,r2,strtlp1 # fill text entries
addl3 _ecmap,$NBPG-1,r1 # end of cmap[]
bbcc $31,r1,strt2 # turn off high order bit
ashl $-9,r1,r1 # last page of kernel data
bisl3 $PG_V|PG_KW,r2,_Sysmap[r2] # fill data entries
# initialize memory controller mapping
bisl3 $PG_V|PG_KW,r1,(r2)
# Initialize I/O space page table entries
movl $PHYSUBA/NBPG,r1 # page frame number for uba
movab UBA0map,r2 # page table address
movab 15(r1),r3 # last pt entry
bisl3 $PG_V|PG_KW,r1,(r2)+ # init pt entry
movab UMEMmap,r2 # page table address
bisl3 $PG_V|PG_KW,r1,(r2)+
bisl3 $PG_V|PG_KW,r1,(r2)+
bisl3 $PG_V|PG_KW,r1,(r2)+
mtpr $1,$TBIA # invalidate all trans buffer entries
mtpr $1,$MAPEN # turn on memory mapping
jmp *$startmap # put system virtual address in pc
# Now we move forward, virtually.
ashl $-9,r7,_maxmem # set maxmem = btoc(r7)
# Setup context for proc[0] == Scheduler
# First page: paget for proc[0]
# Next UPAGES: _u for proc[0]
# Initialize (slightly) the pcb.
bicl2 $NBPG-1,r6 # make page boundary
# set up u area page table
ashl $-9,r6,r3 # r3 = btoc(r6)
bisl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry
moval -4*UPAGES(r0)[r1],r2
bisl3 $PG_V|PG_URKW,r3,-(r0)
movab UPAGES*NBPG(r1),PCB_KSP(r1) # init ksp
mnegl $1,PCB_ESP(r1) # invalidate esp
mnegl $1,PCB_SSP(r1) # invalidate ssp
movl r1,PCB_USP(r1) # set user sp
movb $4,PCB_P0LR+3(r1) # disable ast
movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt
movab strt3c,PCB_PC(r1) # initial pc
clrl PCB_PSL(r1) # mode(k,k), ipl=0
mtpr r3,$PCBB # first pcbb
# set regs, p0br, p0lr, p1br, p1lr
# astlvl, ksp and change to kernel mode
# put signal trampoline code in u. area
movc3 $12,sigcode,PCB_SIGC(r0)
addl3 _ecmap,$NBPG-1,r0 # calculate firstaddr
ashl $-9,r0,-(sp) # convert to clicks and stack
calls $1,_main # startup, fork off /etc/init.vm
# 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
# it is known that this code takes exactly 12 bytes
# in ../h/pcb.h and in the movc3 above
callg (ap),*12(ap) # registers 0-6 (6==sp/compat)
movl 8(ap),r2 # &u.u_prof
subl3 8(r2),4(ap),r0 # corrected pc
extzv $1,$31,r0,r0 # logical right shift
extzv $1,$31,12(r2),r1 # ditto for scale
_Copyin: .globl _Copyin # <<<massaged for jsb by asm.sed>>>
movl 12(sp),r0 # copy length
movl 4(sp),r1 # copy user address
cmpl $NBPG,r0 # probing one page or less ?
prober $3,$NBPG,(r1) # bytes accessible ?
addl2 $NBPG,r1 # incr user address ptr
acbl $NBPG+1,$-NBPG,r0,ciloop # reduce count and loop
prober $3,r0,(r1) # bytes accessible ?
movc3 12(sp),*4(sp),*8(sp)
_Copyout: .globl _Copyout # <<<massaged for jsb by asm.sed >>>
movl 12(sp),r0 # get count
movl 8(sp),r1 # get user address
cmpl $NBPG,r0 # can do in one probew?
probew $3,$NBPG,(r1) # bytes accessible?
addl2 $NBPG,r1 # increment user address
acbl $NBPG+1,$-NBPG,r0,coloop # reduce count and loop
probew $3,r0,(r1) # bytes accessible?
movc3 12(sp),*4(sp),*8(sp)
cmpl r1,sp # must be a pop
# 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
# Setrq(p), using fancy VAX instructions.
# Call should be made at spl6(), and p->p_stat should be SRUN
.globl _Setrq # <<<massaged to jsb by "asm.sed">>>
tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0
movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4
insque (r0),*4(r2) # at end of queue
bbss r1,_whichqs,set2 # mark queue non-empty
# Remrq(p), using fancy VAX instructions
# Call should be made at spl6().
.globl _Remrq # <<<massaged to jsb by "asm.sed">>>
pushab rem3 # it wasn't recorded to be on its q
clrl P_RLINK(r0) ## for firewall checking
# Swtch(), using fancy VAX instructions
_Swtch: # <<<massaged to jsb by "asm.sed">>>
sw1: ffs $0,$32,_whichqs,r0 # look for non-empty queue
mtpr $0,$IPL # must allow interrupts here
brw sw1 # this is an idle loop!
sw1a: mtpr $0x18,$IPL # lock out all so _whichqs==_qs
bbcc r0,_whichqs,sw1 # proc moved via lbolt interrupt
remque *(r1),r2 # r2 = p = highest pri process
bvc sw2 # make sure something was there
insv $1,r0,$1,_whichqs # still more procs in this queue
tstl P_WCHAN(r2) ## firewalls
ashl $PGSHIFT,*P_ADDR(r2),r0 # r0 = pcbb(p)
# mfpr $PCBB,r1 # resume of current proc is easy
.globl _Resume # <<<massaged to jsb by "asm.sed">>>
mtpr $0x18,$IPL # no interrupts, please
movl CMAP2,_u+PCB_CMAP2 # yech
movl _u+PCB_CMAP2,CMAP2 # yech
movl $PSL_PRVMOD,4(sp) # ``cheating'' (jfr)
# {fu,su},{byte,word}, all massaged by asm.sed to jsb's
# Copy 1 relocation unit (NBPG bytes)
# from user virtual address to physical address
_copyseg: .globl _copyseg
mfpr $IPL,r0 # get current pri level
mtpr $HIGH,$IPL # turn off interrupts
bisl3 $PG_V|PG_KW,8(ap),CMAP2
mtpr $CADDR2,$TBIS # invalidate entry for copy
movc3 $NBPG,*4(ap),CADDR2
bicl3 $PG_V|PG_M|PG_KW,CMAP2,r1
mtpr r0,$IPL # restore pri level
# zero out physical memory
# specified in relocation units (NBPG bytes)
_clearseg: .globl _clearseg
mfpr $IPL,r0 # get current pri level
mtpr $HIGH,$IPL # extreme pri level
bisl3 $PG_V|PG_KW,4(ap),CMAP1
movc5 $0,(sp),$0,$NBPG,CADDR1
mtpr r0,$IPL # restore pri level
# Given virtual address, byte count, and rw flag
# returns 0 on no access.
_useracc: .globl _useracc
tstl 12(ap) # test for read access ?
cmpl $NBPG,r1 # can we do it in one probe ?
acbl $NBPG+1,$-NBPG,r1,uaw1
acbl $NBPG+1,$-NBPG,r1,uar1
# kernacc - check for kernel access privileges
# We can't use the probe instruction directly because
# it ors together current and previous mode.
movl 4(ap),r0 # virtual address
mfpr $SBR,r2 # address and length of page table (system)
mfpr $P1BR,r2 # user P1 (stack)
addl3 8(ap),r0,r1 # ending virtual address
ashl $-9,r0,r0 # page number
blss kacerr # address too low
cmpl r1,r3 # compare last page to P0LR or SLR
bgeq kacerr # address too high
bbc $31,r3,kacerr # valid bit is off
cmpzv $27,$4,r3,$1 # check protection code
bleq kacerr # no access allowed
bneq kacc5 # only check read access
cmpzv $27,$2,r3,$3 # check low 2 bits of prot code
beql kacerr # no write access
aobleq r1,r0,kacc4 # next page
# (int) i = udiv( (int)dvdnd , (int) divis)
# unsigned int remainder:
# (int) j = urem( (int)dvdnd , (int) divis)
ediv 8(ap),r0,r0,r1 # quotient in r0
# ediv 8(ap),r0,r1,r0 # remainder in r0
SBImsg: .asciz "SBI fault\n"
UBAmsg: .asciz "UBA error UBASR %X, FMER %X, FUBAR %X\n"
straym: .asciz "Stray Interrupt\n"
# these should be memall'ed
_buffers: .space NBUF*BSIZE
# This is needed when running old-style switch code.
# Be sure to enable setting of idleflag in interrupt code above also.
# mtpr $0,$IPL # enable interrupts
# blbc idleflag,waitloc # loop until interrupt
# bbcci $0,idleflag,idle1 # clear idle escape flag
#_ewaitloc: .long ewaitloc