Ausam/sys/conf/m70.snew
/ options.
.ht = 1 / tu-16 is dump device
.mt = 0 / tu-10 is dump device
.pdp70 = 1 / 11/70 is target machine
.fp = 1 / floating point processor present
.hpdisk = 0 / enable ecc error correction code for hp disk
.newputc = 1 / set if want new superior getc/putc
.display = 1 / enable location 52 as magic pattern !!
.swtchdsp = 1 / enable location 70 as switch count
/ really needs .display as well
.idle = 0 / 0=> place idle in l70.s 1=> place idle here
.powerfail = 0 / 1=> support for powerfail 0=> no support
.systime = 1 / 1=> code for _systime generated
.bufmap = 1 / buffers addressed by KA5
.ubmapd = 1 / used with above change if unibus devices
.profile = 0 / enable the profiling
/ indicate highest priority at which character queues
/ will be accessed
_spl_tty = _spl5
tty_prio = 5
/ machine language assist for a pdp-11/70 with fpp
/ extended and (improved) J. N. Rottman
/ This code will also work on an 11/45 if the test on the
/ CPU error register is replaced with a slower direct comparison
/ on the kernal SP. (pdp70=0)
/ External definitions for l.s
.globl dump, start, call, code00, code01, code02, code03
.globl code04, code05, code06, pirqi
/ External data references
.globl _etext, _edata, _end, _regloc, _cfreelist, _cfreecount
.globl _runrun
/ External text references
.globl _main, _trap, _swtch, _wakeup
/ External data definitions
.globl _ka6, _cputype, nofault, ssr, _u, _uufec, _uufsav
/ External text definitions
.globl _savfp, _incupc, _display, _getc, _putc, _backup
.globl _fubyte, _fuword, _subyte, _suword, loadfp
.globl _fuibyte, _suibyte, _fuiword, _suiword, _spl_tty
.globl _savu, _retu, _aretu
.if .idle
.globl _idle
.endif
.if .bufmap
.globl _bswtch, _bufarea, _b
.endif
.if .display
.globl diswflag
.endif
.if .swtchdsp
.globl _swi_count,_lst_count
.endif
.globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7
.globl _copyin, _copyout, _clearseg, _copyseg
.globl _dpcmp, _ldiv, _longdiv, _lrem, csv, cret
.globl _btoc, _itol
.globl _systime, _time
/ Non-unix instructions
mfpi = 6500 ^ tst
mtpi = 6600 ^ tst
mfpd = 106500 ^ tst
mtpd = 106600 ^ tst
spl = 230
ldfps = 170100 ^ tst
stfps = 170200 ^ tst
stst = 170300 ^ tst
wait = 1
rti = 2
rtt = 6
halt = 0
reset = 5
/
/ Mag-tape dump.
/ Save the registers in low core and write all
/ of core onto magtape. Entry is from 44 abs.
/
/ Registers r0, r1, r2, r3, r4, r5, r6, KIA6
/ are saved in low core starting at location 4.
/ The blocksize for the type is 512. bytes.
/
.data
dump: mov r0, 4
mov $6,r0
mov r1,(r0)+
mov r2,(r0)+
mov r3,(r0)+
mov r4,(r0)+
mov r5,(r0)+
mov sp,(r0)+
mov KDSA6,(r0)+
.if .bufmap
mov KDSA5,(r0)+
.endif
mov pc,46 / protect in case of restart
.if .mt
mov $MTC,r0
mov $60004,(r0)+
clr 2(r0)
1: mov $-512.,(r0)
inc -(r0)
2: tstb (r0)
bge 2b
tst (r0)+
bge 1b
reset
mov $60007,-(r0)
br .
.endif
.if .ht
reset
mov $1300,*$HTTC
mov $HTCS1,r0
mov $60,(r0)
1:
mov $177000,*$HTFC
mov $177400,*$HTWC
inc (r0)
2:
tstb (r0)
bge 2b
tst (r0)
bge 1b
mov $27,(r0)
br .
HTCS1 = 172440
HTWC = 172442
HTBA = 172444
HTFC = 172446
HTCS2 = 172450
HTTC = 172472
.endif
/ Startup code. Since core is shuffled, this code can
/ be execute but once.
start: mov $code15,*$0 / set to catch spurious interrupts
/ also prevent restart from zero
reset
clr PS / These things are not defined after reset
.if .pdp70
clr CPUERR
mov $-1,MEMERR
.endif
/ set KIO to physical 0
mov $77406,r3
mov $KISA0,r0
mov $KISD0,r1
clr (r0)+
mov r3,(r1)+
/ set KI1-6 to eventual text resting place
mov $_end+63.,r2
ash $-6,r2
bic $!1777,r2
1: mov r2,(r0)+
mov r3,(r1)+
add $200,r2
cmp r0,$KISA7
blos 1b
/ set KI7 to IO segment for escape
mov $IO,-(r0)
/ set KD0-7 to physical
mov $KDSA0,r0
mov $KDSD0,r1
clr r2
1: mov r2,(r0)+
mov r3,(r1)+
add $200,r2
cmp r0,$KDSA7
blos 1b
/ Initialization :
/ get a temporary 1-word stack and turn on
/ segmentation. Then copy text to I space
/ and clear the bss in data space.
mov $stk+2,sp
mov $65,SSR3 / 22-bit map, K+U sep.
bit $20,SSR3
beq 1f
mov $70.,_cputype
1: inc SSR0
mov $_etext,r0
mov $_edata,r1
add $_etext-8192.,r1
1: mov -(r1),-(sp)
mtpi -(r0)
cmp r1,$_edata
bhi 1b
1: clr (r1)+
cmp r1,$_end
blo 1b
/ Use KI escape to set KD7 to IO segment. Set KD6 to the
/ first available core to serve as the swap process's
/ u-table
mov $IO,-(sp)
mtpi *$KDSA7
mov $_etext-8192.+63.,r2
ash $-6,r2
bic $!1777,r2
add KISA1,r2
mov r2,KDSA6
mov $7406,KDSD6 / USIZE long only (RW)
/ Set up the real stack at the top of the u-table, and
/ clear the rest of it
mov $_u+[usize*64.],sp
mov $_u,r0
1: clr (r0)+
cmp r0,sp
blo 1b
.if .bufmap
/ set up KDSA5 for buffer pointer
mov KDSA7,KDSA5 / hopefully illegal
mov $3406,KDSD5 / 512 bytes, RW
.endif
/ Start system profiling
/ jsr pc,_isprof
/ Set up previous mode as user mode and call main.
/ On return, enter user mode at 0R
mov $30000,PS
jsr pc,_main
mov $170000,-(sp)
clr -(sp)
rtt
.text
/ Entry to the system from all traps, interrupts, and aborts is
/ handled in the following code.
/
/ Each device's vector contains a new kernal PS at the device's
/ bus grant priority, and a pointer to a code segment of the
/ form:
/ jsr r0,call; _xxxxxxx
/ where `xxxxxxx' is the name of the device's interrupt routine.
/
/ Traps and aborts are more complicated. Entry is always in
/ kernal mode at priority 7, and enters the following routines:
/
/ 1) code00 Floating point asynchronous interrupt. If
/ the user is active, the interrupt is reported
/ back immediately. Otherwise, since the interrupt
/ is asynchronous, it could occur from kernal mode
/ or supervisor mode. In this case the interrupt is
/ just posted for the user, and if the interrupted
/ priority is high, the actual processing is PIRQ'd
/ at priority 1. Since the FEA and FEC are volitile,
/ they are saved when the interrupt occurs. They
/ cannot be restored, but may be retrieved via a system
/ call.
/
/ 2) code01 IOT. If the request came from the supervisor state,
/ it is a request for an interrupt exit from a super-
/ visor interrupt handler. The handler could not do
/ the rti directly since it could have interrupted a kernal
/ task.
/ If the previous mode was user mode, the trap
/ is posted in the usual way. For efficiency, no check
/ is made to distinguish supervisor from kernal iot's,
/ which should never occur.
/
/ 3) code02 BPT/trace trap, illegal instruction, system entry:
/ If these are from the user they are handled in the
/ standard manner.
/ Any of these calls from the supervisor abort
/ it with an indicative error code.
/ Any of these calls from the kernal are fatal.
/
/ 4) code03 Parity errors.
/ errors.
/
/ 5) code04 EMT. If this code is from the supervisor, it is a
/ request for a kernal function. If the function code
/ is legal, the function is performed and control returns;
/ otherwise, the supervisor is aborted.
/ From user mode this is just a trappable signal.
/
/ 6) code05 Bus error. The cpu error register is interrogated to
/ see if this a stack overflow (code07) or a bus error.
/ The following applies just to real bus errors:
/ nofault_______ is checked; if it is non-zero it is
/ the address of an error catching routine to which control
/ should be returned on the rti. Otherwise, bus errors
/ are handled like class (3).
/
/ 7) code06 Segmentation violation. If nofault is set, the
/ segmentation error registers are thawed, and control
/ returns immediately. If the error comes from super-
/ visor state, the supervisor is aborted. If it comes
/ from kernal state, the system dies. If it comes from
/ user state, the error registers are saved for a possible
/ stack page fault backup.
/
/ 8) code07 Bad PIRQ, stack overfow. (see (6)). These are fatal
/ software botches.
/
/
/ The codes reported to trap are:
/ NON-FATAL
/ 0 User floating point exception
/ 1 Kernal floating point exception
/ 2 Illegal instruction
/ 3 BPT/trace trap
/ 4 SYS entry
/ 5 IOT
/ 6 EMT
/ 7 Bus error
/ 10 Segmentation violation
/ 12 Parity
/ 15 Trap thru location zero
/ 16 Power fail recovery completed
/ ( trap is called from powerf.s )
/ FATAL-
/ 22 Kernal illegal instruction
/ 23 Kernal BPT
/ 24 Kernal SYS
/ 25 Kernal IOT
/ 26 Kernal EMT
/ 27 Kernal Bus error
/ 30 Kernal Segmentation
/ 32 Kernal parity
/ 33 Bad PIRQ
/ 34 Stack limit overflow
/
code00: stst *_uufec / save FEC and FEA in active u
bit $340,2(sp) / from high priority ?
beq codeff / no - handle immediately
bis $PIRQ1,PIRQ / set for later processing
rti / and split
pirq1: bic $PIRQ1,PIRQ / dispatch from PIRQ request 1
codeff: clr -(sp) / trap code
bit $20000,PS / from user mode ?
bne 1f / yes
inc (sp) / set to post and leave
1: br callt1 / don't add in displacment
pirq2:
pirq3:
pirq4:
pirq5:
pirq6:
pirq7:
clr PIRQ / Illegal PIRQ's - clear register
mov $33,-(sp) / set code
br callt1 / report fatal error
code05:
.if .pdp70 / Use CPU error register
mov CPUERR,_cpuereg / get CPU error register
clr CPUERR / now reset it !
bit $14,_cpuereg / yellow/red stack violation ??
bne 3f / yes, so branch.
bit $160,_cpuereg / odd addr, bus timeout, no mem?
bne 1f / yes, so branch
bit $200,_cpuereg / no, but illegal halt ??
beq 1f / no, so branch
mov $2,-(sp) / yes, set illegal instruction
br callt1
.bss
slrbef: . = . + 2
r0save: . = . + 2
.globl spsave
spsave: . = . + 2
.globl _cpuereg
_cpuereg: . = . + 2
.text
3:
tst slrbef / prior stack limit trap ??
bne 9f / --> yes
bit $4,_cpuereg
beq 8f / --> YELLOW Violation
9:
mov r0,r0save
mov sp,spsave
mov sp,r0 / save current (offending??) sp
mov $142000,sp / reset stack.
mov 2(r0),-(sp) / save the troublesome ps
mov (r0),-(sp) / save the troublesome pc
mov r0save,r0
br 7f
8: sub $400,SLR / let the yellow happen
inc slrbef / indicate we already got one !!
7:
/*agsm
mov $34,-(sp) / report code
br callt1
.endif
1: tst nofault / catchable?
beq 1f / no
2: mov nofault,(sp) / adjust return
rti / exit
1: mov $7,-(sp) / proper code
br callt
code06: tst nofault / catchable ?
beq 1f / no
mov $1,SSR0 / thaw registers
br 2b / and take nofault exit
1: bit $20000,PS / user mode ?
beq 1f / no - don't overwrite ssr
mov SSR0,ssr / save for possible backup
mov SSR1,ssr+2
mov SSR2,ssr+4
1: mov $1,SSR0 / thaw error registers
mov $10,-(sp) / segmentation code
br callt
code03: / Parity. Try to be clever about it.
.if .pdp70
bis $3,MEMCNTRL / disable traps for ....
/ don't want multiple errors
/ unless they are aborts
mov MEMERR,_memereg / Save Mem error register
mov MEMHIA,_memhigha
mov MEMLOA,_memlowa
mov _memereg,MEMERR / turn off error bits
mov $12,-(sp) / trap type is 12
bit $101000,_memereg/ fatal error ??
beq callt1 / --> no, just flag as a parity error
tst nofault / is the error capable of being caught ??
beq callt / --> no, clobber user/system then
mov nofault,2(sp) / fix return from trap
br callt1 / and treat as simple parity error
.endif
.if .pdp70 - 1
mov $12,-(sp) / Trap type 12
br callt
.endif
.if .pdp70
.bss
.globl _memhigha, _memlowa, _memereg
_memereg: . = . + 2
_memhigha: . = . + 2
_memlowa: . = . + 2
.text
.endif
code15: / Hardware-type botches
mov PS,-(sp) / previous mode is unimportant
br callt2 / so ignore it here
code01:
code02:
code04: mov PS,-(sp) / save emt trap code
/ br callt
callt:
bit $20000,PS / user fault ??
bne callt1 / --> yes
add $20,(sp) / indicate kernal fault
callt1:
spl 0 / out of critical section
callt2: / entry if not to drop pri
mov (sp),-(sp) / save device code
mov r0,2(sp)
mov r1,-(sp)
mfpd sp / get a sp
mov 4(sp),-(sp) / device again
mov $1f,r0 / point to trap
br 2f
.data; 1: _trap; .text
call: mov PS,-(sp) / Entry from device interrupt vector
mov r1,-(sp)
mfpd sp
mov 4(sp),-(sp)
.if .powerfail
.globl _powflag
2: tst _powflag / powerfail in progress ??
beq 2f / --> NO
inc _powflag
halt
.endif
2: bic $!37,(sp) / extra bits in code bit 4 indicates user/kernal
mov nofault,6(sp)
clr nofault / catch errors
bit $20000,PS / from user mode ?
beq 1f / no - call routine and split
mov $20,*_uufsav / set maint. bit
jsr pc,*(r0)+ / call routine
2: spl 6 / interlock
tstb _runrun
beq 2f / see if we should schedule
spl 0 / end of interlock
jsr pc,_savfp
jsr pc,_swtch
br 2b
2: jsr pc,loadfp
tst (sp)+ / "dev"
mtpd sp
br 2f
1: jsr pc,*(r0)+
cmp (sp)+,(sp)+ / dump dev and sp
2: mov (sp)+,r1
mov (sp)+,nofault
mov (sp)+,r0
/ fix015 gregr & chrism
/ to make t bit tracing work properly
bit $3400,2(sp)
bne 1f
rti
1: bic $3400,2(sp)
/ end of fix015
rtt
/
/
/ PIRQ interrupt
/
pirqi: mov PIRQ,-(sp) / PIRQ interrupt dispatch
movb (sp),PS / set to active PIRQ priority
bic $!16,(sp) / prepare word dispatch
add $1f-2,(sp)
mov *(sp)+,pc / disptach on PIRQ priority
.data; 1: pirq1; pirq2; pirq3; pirq4; pirq5; pirq6; pirq7; .text
/
/ Save the user's floating point registers.
/ Use the maint. bit to indicate if done.
/
_savfp:
.if .fp
mov _uufsav,r1
bit $20,(r1)
beq 1f
stfps (r1)+
movf fr0,(r1)+
movf fr4,fr0
movf fr0,(r1)+
movf fr5,fr0
movf fr0,(r1)+
movf fr1,(r1)+
movf fr2,(r1)+
movf fr3,(r1)+
.endif
1: rts pc
/
/ Reload the user's floating point registers.
/
loadfp:
.if .fp
mov _uufsav,r1
bit $20,(r1) / floating registers saved?
bne 1f / no
mov (r1),r0 / saved fps
bic $4000,(r1) / interrupt on floating undefined
ldfps (r1)+
movf (r1)+,fr0
movf (r1)+,fr1
movf fr1,fr4
movf (r1)+,fr1
movf fr1,fr5
movf (r1)+,fr1
movf (r1)+,fr2
movf (r1)+,fr3
ldfps r0 / user's cc's
.endif
1: rts pc
/
/ Handle counts for user profiles
/
_incupc:
mov r2,-(sp)
mov 6(sp),r2 / base of prof with base, leng, off, scale
mov 4(sp),r0 / pc
sub 4(r2),r0 / offset
clc
ror r0
mul 6(r2),r0 / scale
ashc $-14.,r0
inc r1
bic $1,r1
cmp r1,2(r2) / length
bhis 1f
add (r2),r1 / base
mov $2f,nofault
mfpd (r1)
inc (sp)
mtpd (r1)
br 3f
2: clr 6(r2)
3: clr nofault
1: mov (sp)+,r2
rts pc
/
/ Display the contents of the word whose address is
/ in the switch registers. If bit 0 is set, the word
/ refers to supervisor space; otherwise, it refers to
/ kernal data space
/
_display:
.if .display
tst diswflag //// previously waiting ??
bne 0f //// -> yes.
mov $5,displw //// slow up the display.
br 2f
0: clr diswflag
dec displw
jge 2f //// -> display not to change
mov $2,displw
mov dispat+0,r0
mov dispat+2,r1
ashc dishift,r0 //// form next dispat in sequence
mov r0,dispat+0
mov r1,dispat+2
ashc $8.,r0 //// extract the dispat for display
bit $077776,r0 //// need to start dishifting the other way ??
bne 1f //// -> no.
neg dishift
1: mov r0,*$52 //// store for later display
2:
.data
dispat: 17;0 //// starting pattern (only use middle 22 bits)
dishift: 1 //// either 1 or -1 (the dishift direction)
displw: 1 //// use to delay the display
diswflag: 0 //// set by _idle to indicate wait done
.text
.endif
.if .swtchdsp
bit $7,*$56 /// low word of clk tiks
bne 1f /// no change to display
mov _lst_count,r0
add _swi_count,r0
asr r0
mov r0,_lst_count
clr _swi_count
mov $177777,r1
ash r0,r1
com r1
mov r1,*$70 /// save here for later display
1:
.endif
mov PS,-(sp)
mov $30300,PS / previous mode is user
mov $3f,nofault
1: mov CSW,r1
bit $1,r1
beq 1f
dec r1
mfpi (r1)
mov (sp)+,r0
br 4f
1: mov (r1),r0
4: mov r0,CSW
3: clr nofault
mov (sp)+,PS
rts pc
/
/ Character list get/put
/
.if .newputc
.globl _cblockm, _cblockl
/ c = getc( cp ) struct clist *cp;
_getc:
mov r2,-(sp)
mov 4(sp),r2
mov PS,-(sp)
spl 6
mov 2(r2),r1 / first ptr
beq 5f / buffer empty
0:
movb (r1)+,r0
bic $!377,r0
dec (r2)+ / update count
beq 4f / return last block to free
bit _cblockm,r1
beq 2f / return empty block to free
mov r1,(r2)
1:
mov (sp)+,PS
mov (sp)+,r2
rts pc
2:
sub _cblockl,r1
mov (r1),(r2)
add $2,(r2) / update first pointer
3:
mov _cfreelist,(r1)
mov r1,_cfreelist
br 1b
4:
clr (r2)+
clr (r2)
dec r1
bic _cblockm,r1
br 3b
5:
mov $-1,r0
br 1b
/ putc( c , cp ) struct clist *cp;
_putc:
mov 4(sp),r0
mov PS,-(sp)
spl 6
mov 4(r0),r1 / last ptr
beq 4f / buffer empty
bit _cblockm,r1
beq 2f / block full
0:
movb 4(sp),(r1)+
mov r1,4(r0)
inc (r0) / update count
clr r0
1:
mov (sp)+,PS
rts pc
2:
sub _cblockl,r1
mov _cfreelist,-(sp)
beq 3f / freelist empty ( r0 != 0 )
mov *(sp),_cfreelist
mov (sp),(r1)
mov (sp)+,r1
clr (r1)+
br 0b
3:
tst (sp)+
br 1b
4:
mov _cfreelist,r1
beq 1b / freelist empty ( r0 != 0 )
mov (r1),_cfreelist
clr (r1)+
mov r1,2(r0) / set first ptr
br 0b
.endif
.if .newputc - 1
_getc: mov 2(sp),r1
mov PS,-(sp)
mov r2,-(sp)
spl tty_prio
mov 2(r1),r2 / first ptr
beq 9f / empty
movb (r2)+,r0 / character
bic $!377,r0
mov r2,2(r1)
dec (r1)+
bne 1f
clr (r1)+
clr (r1)+ / last ptr
br 2f
1: bit $7,r2
bne 3f
mov -10(r2),(r1) / next block
add $2,(r1)
2: dec r2
bic $7,r2
mov _cfreelist,(r2)
mov r2,_cfreelist
inc _cfreecount
3: mov (sp)+,r2
mov (sp)+,PS
rts pc
9: clr 4(r1)
mov $-1,r0
br 3b
_putc: mov 2(sp),r0
mov 4(sp),r1
mov PS,-(sp)
mov r2,-(sp)
mov r3,-(sp)
spl tty_prio
mov 4(r1),r2 / last ptr
bne 1f
mov _cfreelist,r2
beq 9f
mov (r2),_cfreelist
dec _cfreecount
clr (r2)+
mov r2,2(r1)
br 2f
1: bit $7,r2
bne 2f
mov _cfreelist,r3
beq 9f
mov (r3),_cfreelist
dec _cfreecount
mov r3,-10(r2)
mov r3,r2
clr (r2)+
2: movb r0,(r2)+
mov r2,4(r1)
inc (r1)
clr r0
3: mov (sp)+,r3
mov (sp)+,r2
mov (sp)+,PS
rts pc
9: mov pc,r0
br 3b
.endif
/
/ Backup a user's registers after a stack page
/ fault
/
_backup:
mov 2(sp),r0
movb ssr+2,r1
jsr pc,1f
movb ssr+3,r1
jsr pc,1f
movb _regloc+7,r1
asl r1
add r0,r1
mov ssr+4,(r1)
clr r0
rts pc
1: mov r1,-(sp)
asr (sp)
asr (sp)
asr (sp)
bic $!7,r1
movb _regloc(r1),r1
asl r1
add r0,r1
sub (sp)+,(r1)
rts pc
/
/ Interspace communitcation routines
/
_fuibyte:
mov 2(sp),r1
bic $1,r1
jsr pc,giword
br 2f
_fubyte:
mov 2(sp),r1
bic $1,r1
jsr pc,gword
2: cmp r1,2(sp)
beq 1f
swab r0
1: bic $!377,r0
rts pc
_suibyte:
mov 2(sp),r1
bic $1,r1
jsr pc,giword
mov r0,-(sp)
cmp r1,4(sp)
beq 1f
movb 6(sp),1(sp)
br 2f
1: movb 6(sp),(sp)
2: mov (sp)+,r0
jsr pc,piword
rts pc
_subyte:
mov 2(sp),r1
bic $1,r1
jsr pc,gword
mov r0,-(sp)
cmp r1,4(sp)
beq 1f
movb 6(sp),1(sp)
br 2f
1: movb 6(sp),(sp)
2: mov (sp)+,r0
jsr pc,pword
rts pc
_fuiword:
mov 2(sp),r1
jsr pc,giword
rts pc
_fuword:
mov 2(sp),r1
jsr pc,gword
rts pc
giword:
mov $err,nofault
mfpi (r1)
br 1f
gword:
mov $err,nofault
mfpd (r1)
1: mov (sp)+,r0
br 2f
_suiword:
mov 2(sp),r1
mov 4(sp),r0
jsr pc,piword
rts pc
_suword:
mov 2(sp),r1
mov 4(sp),r0
jsr pc,pword
rts pc
piword:
mov $err,nofault
mov r0,-(sp)
mtpi (r1)
br 1f
pword:
mov $err,nofault
mov r0,-(sp)
mtpd (r1)
1: clr r0
2: clr nofault
rts pc
err: mov $-1,r0
tst (sp)+
br 2b
/
/ Block/word transfers to/from kernal/user/supervisor space
/
/
/ call from C is
/ copy[in/out](from, to, byte_count, segflag)
/ on entry previous mode must be user
/ from and to must be even addresses,
/ byte_count must also be even
/ segflag is:
/ 0: to/from user data
/ 1: to/form kernal data
/ 2: to/from user text
/ 3: to/from supervisor region
_copyin:
jsr pc,copsu
br 4f / transfer from user data
br 2f / transfer from kernal data
br 1f / transfer from supervisor
1: mfpi (r0)+
mov (sp)+,(r1)+
sob r2,1b
br 5f
2: mov (r0)+,(r1)+ / transfer from krnal data
sob r2,2b / word count
br 5f
4: mfpd (r0)+ / transfer from user data
mov (sp)+,(r1)+
sob r2,4b
br 5f
_copyout:
jsr pc,copsu
br 4f / transfer to user data
br 2b / transfer to system data
br 3f / transfer to user text
3: mov (r0)+,-(sp) / transfer to supervisor i/d
mtpi (r1)+
sob r2,3b
br 5f
4: mov (r0)+,-(sp)
mtpd (r1)+ / transfer to user data
sob r2,4b
5: clr r0 / successful transfer
6: mov (sp)+,PS / common exit
clr nofault
mov (sp)+,r2 / count register
rts pc / exit
copsu: mov (sp)+,r0 / general set-up for copyxx
mov r2,-(sp)
mov PS,-(sp)
mov 14(sp),-(sp) / get segflag
cmp (sp),$3 / if its to supervisor mod
bne 1f / then set previous mode
bic $20000,PS / to supervisor mode
1: asl (sp) / word displacment
add r0,(sp) /return address
mov 10(sp),r0 / from
mov 12(sp),r1 / to
mov 14(sp),r2 / byte count
asr r2 / to word count
mov $1f,nofault / error catcher
rts pc / to offset branch
1: mov $-1,r0 / error catcher
br 6b / exit with indicator
.if .idle
/
/ Just idle while nothing is active to speed up transfers
/
_idle:
.if .display
inc diswflag / indicate wait in progress
.endif
wait
rts pc
.endif
/
/ Routines to do context switching
/
_savu: mov (sp)+,r1
mov (sp),r0
mov sp,(r0)+
mov r5,(r0)+
.if .bufmap
mov KDSA5,(r0)+ /buffer address
.endif
jmp (r1)
_aretu: mov (sp)+,r1
mov (sp),r0
spl 7 / critical part where stack is switched
br 1f
_retu: mov (sp)+,r1
spl 7 / critical region
mov (sp),KDSA6
mov $_u,r0
1:
mov (r0)+,sp
mov (r0)+,r5
.if .bufmap
mov (r0)+,KDSA5
.endif
spl 0
jmp (r1)
_bswtch:
.if .bufmap
/ converts a buffer header pointer
/ to a memory block reference and sets KA5
baddr = 16 / offset of b_addr in buf header struct
mov 2(sp),r0
mov baddr(r0),r1
mov baddr+2(r0),r0
ashc $-6,r0
.if .ubmapd
add _bufarea,r1
.endif
mov r1,KDSA5
.endif
rts pc
/
/ Routine to set priorities
/
_spl0: spl 0
rts pc
_spl1: spl 1
rts pc
_spl4: spl 4
rts pc
_spl5: spl 5
rts pc
_spl6: spl 6
rts pc
_spl7: spl 7
rts pc
/
/ Copy and clear user sements (64 bytes)
/ Called with previous mode = user mode
/
_copyseg:
mov UISA0,-(sp) / appropriate bottom two user regs.
mov UISA1,-(sp)
mov UISD0,-(sp)
mov UISD1,-(sp)
mov 12(sp),UISA0 /from segment
mov 14(sp),UISA1 / to segment
mov $6,UISD0
mov $6,UISD1
mov r2,-(sp)
clr r0
mov $8192.,r1
mov $32.,r2
1: mfpi (r0)+ / get a word
mtpi (r1)+ / put a word
sob r2,1b / loop 'till done
mov (sp)+,r2
mov (sp)+,UISD1
mov (sp)+,UISD0
mov (sp)+,UISA1
mov (sp)+,UISA0
rts pc
_clearseg:
mov UISA0,-(sp) / get a user register
mov UISD0,-(sp)
mov 6(sp),UISA0
mov $6,UISD0
mov $32.,r1
clr r0
1: clr -(sp) / clear 32. words
mtpi (r0)+
sob r1,1b
mov (sp)+,UISD0
mov (sp)+,UISA0
rts pc
.if .hpdisk
.globl _hpecc
/
/ Error correction for hp disk
/
_hpecc:
mov r3,-(sp) / save some registers
mov r2,-(sp)
mov UISA0,-(sp) / and some segmentation registers
mov UISD0,-(sp)
mov PS,-(sp) / for previous mode set
mov HPPOS,r3 / bit position of error burst
dec r3 / adjust for zero offset
clr r2 / into word and bit pair
div $16.,r2 / r2 word, r3 bit offset
mov r2,-(sp) / save for later end check
mov r2,r1 / convert to bytes
asl r1
sub $512.,r1 / back up one sector
sxt r0 / will be negative always
add HPBAE,r0 / high order physical address
add HPBA,r1 / low order physical address
adc r0 / long arithmetic
div $64.,r0 / into KT-11 pages
bis $30000,PS / previous is now user mode
mov $406,UISD0 / short read/write page (128 bytes)
mov r0,UISA0 / into this page
mov r1,r2 / word offset in block
mov HPPAT,r1 / get correction pattern
clr r0 / double precision
ashc r3,r0 / fix by bit offset
mfpi (r2) / get first word
xor r1,(sp) / fix low order
mtpi (r2)+ / replace word
cmp (sp)+,$255 / don't exceed block
beq 1f / only one word correction
mfpi (r2) / fetch second word
xor r0,(sp) / high order correction
mtpi (r2) / and replace word
1:
mov (sp)+,PS / now do the mandatory restore
mov (sp)+,UISD0 / sequence
mov (sp)+,UISA0
mov (sp)+,r2
mov (sp)+,r3
mov HPWC,r0 / see if in mid-transfer
beq 1f / no - return 0, we're done
inc HPCS1 / complete transfer and return(!=0)
1:
rts pc
HPCS1 = 176700 / Disk registers used above
HPWC = 176702
HPBA = 176704
HPPOS = 176744
HPPAT = 176746
HPBAE = 176750
.endif
/ General utility routines
/
_btoc: mov 2(sp),r1
clr r0
add $63.,r1
adc r0
ashc $-6,r0
mov r1,r0
rts pc
_dpcmp: mov 2(sp),r0
mov 4(sp),r1
sub 6(sp),r0
sub 8(sp),r1
sbc r0
bge 1f
cmp r0,$-1
bne 2f
cmp r1,$-512.
bhi 3f
2: mov $-512.,r0
rts pc
1: bne 2f
cmp r1,$512.
blo 3f
2: mov $512.,r1
3: mov r1,r0
rts pc
_ldiv: clr r0
mov 2(sp),r1
div 4(sp),r0
rts pc
_longdiv:
mov 2(sp),r0
mov 4(sp),r1
div 6(sp),r0
rts pc
_lrem: clr r0
mov 2(sp),r1
div 4(sp),r0
mov r1,r0
rts pc
/ routine to return a address of string representing
/ system idea of the time
/ call systime( &string )
/ string to contain after call 'hh:mm'
_systime:
.if .systime
jsr r5,csv / save registers
mov 4(r5),r4 / address of string area
add $6,r4 / address end of string
clrb -(r4) / null at end
mov _time,r0 / get systems idea of time
mov _time+2,r1
div $28800.,r0 / r0= no of 8 hr lots since start 1970
/ r1= no of seconds into 8 hour lot
mov r0,r3
clr r2
div $3,r2 / r2= no of days since start of 1970
/ r3= no of 8 hours in day
clr r0
div $60.,r0 / r0= no of minutes
mov r0,r1
clr r0
div $60.,r0 / r0= no of hour into 8 hr grp
/ r1= no of minutes
jsr pc,numbin / put in minutes
movb $':,-(r4) / separator
mov r3,r1
mul $8.,r1
add r0,r1 / r1= no of hours
jsr pc,numbin / put in hours
mov r4,r0 / pass back address of string
jmp cret / return
numbin:
mov r0,-(sp)
clr r0
div $10.,r0
bis $'0,r0
bis $'0,r1
movb r1,-(r4)
movb r0,-(r4)
mov (sp)+,r0
.endif
rts pc
_itol: mov 4(sp),r1
mov 2(sp),r0
rts pc
csv: mov r5,r0
mov sp,r5
mov r4,-(sp)
mov r3,-(sp)
mov r2,-(sp)
jsr pc,(r0)
cret: mov r5,r2
mov -(r2),r4
mov -(r2),r3
mov -(r2),r2
mov r5,sp
mov (sp)+,r5
rts pc
_u = 140000
usize = 16.
.if .bufmap
_b = 120000
bsize = 8.
.endif
CSW = 177570
PS = 177776
SSR0 = 177572
SSR1 = 177574
SSR2 = 177576
SSR3 = 172516
KISA0 = 172340
KISA1 = 172342
KISA7 = 172356
KISD0 = 172300
KDSA0 = 172360
KDSA5 = 172372
KDSA6 = 172374
KDSA7 = 172376
KDSD0 = 172320
KDSD5 = 172332
KDSD6 = 172334
SISD0 = 172200
SISA0 = 172240
SISD7 = 172216
SISD6 = 172214
SISA6 = 172254
MTC = 172522
UISA0 = 177640 / user instruction address 0
UISA1 = 177642 / user instruction address 1
UISD0 = 177600 / user instruction descriptor 0
UISD1 = 177602 / user instruction descriptor 1
PIRQ = 177772 / program interrupt request
PIRQ1 = 001000 / request at priority 1
PIRQ2 = 002000 / request at priority 2
PIRQ3 = 004000 / request at priority 3
PIRQ4 = 010000 / request at priority 4
PIRQ5 = 020000 / request at priority 5
PIRQ6 = 040000 / request at priority 6
PIRQ7 = 100000 / request at priority 7
.if .pdp70
MEMLOA = 177740 / low address of parity
MEMHIA = 177742 / hi address of parity
MEMERR = 177744 / memory system error register
MEMCNTRL= 177746 / memory control register
CPUERR = 177766 / cpu error register
.endif
SLR = 177774 / stack limit register
IO = 177600
.data
_ka6: KDSA6 / pointer to u-page segment address register
_cputype: 45. / pdp-11/45 or pdp-11/70
stk: 0 / one word stack for segmentation set-up
.bss
nofault: .=.+2 / bus error/segmentation violation bypass
ssr: .=.+6 / saved backup registers
_cfreecount: .=.+2 / free character count
.text
/ system profiler
/
/CCSB = 172542
/CCSR = 172540
/
/.globl _sprof, _xprobuf, _probuf, _probsiz, _mode
/_probsiz = 7500.
/
/_isprof:
/ mov $_sprof,104 / interrupt
/ mov $340,106 / pri
/ mov $100.,CCSB / count set = 100
/ mov $113,CCSR / count down, 10kHz, repeat
/ rts pc
/
/_sprof:
/ mov r0,-(sp)
/ mov PS,r0
/ ash $-10.,r0
/ bic $!14,r0
/ add $1,_mode+2(r0)
/ adc _mode(r0)
/ tst r0 / see if user
/ bne done
/ mov 2(sp),r0 / pc
/ sub $8192.,r0 / low page
/ asr r0
/ asr r0
/ bic $140001,r0
/ cmp r0,$_probsiz
/ blo 1f
/ inc _outside
/ br done
/1:
/ inc _probuf(r0)
/ bne done
/ mov r1,-(sp)
/ mov $_xprobuf,r1
/2:
/ cmp (r1)+,r0
/ bne 3f
/ inc (r1)
/ br 4f
/3:
/ tst (r1)+
/ bne 2b
/ mov $1,-(r1)
/ mov r0,-(r1)
/4:
/ mov (sp)+,r1
/done:
/ mov (sp)+,r0
/ mov $113,CCSR
/ rtt
/
/.bss
/_xprobuf: .=.+512.
/_probuf:.=.+_probsiz
/_mode: .=.+16.
/_outside: .=.+2
.text
.globl _halt
_halt:
mov 2(sp),*$CSW
halt
rts pc
.if .profile
/ New System Profiler - Greg Rose july 78.
.globl _profstart,_pshift,_pmask,_pusertix,_pfreq,_pnbytes
.bss
_profstart: . = . + 2 / start addr of profile area (64 byte blocks)
_pusertix: . = . + 4 / long number of ticks in user space
_pnbytes: . = . + 2 / number of bytes in the profile area
_pshift = 0 / number of bits shift for addr
_pmask = [177777 \< [16.-_pshift]] | 3 / bits to turn off after shifting
_pfreq = 50. / number of 10micros between ticks (no relation to HZ)
/ Note - initialisation is all done in once.c, since it allocates core for the
/ profile buffer, and it's easier there.
.text
.globl profile
profile:
bit $030000,2(sp) / test previous processor mode
bne 1f / branch if was user
mov r0,-(sp)
mov 2(sp),r0 / old pc
ash $_pshift,r0
bic $_pmask,r0
mov $010340,PS
mfpd (r0) / fetch first word - note reverse of a normal long
inc (sp)
bne 2f
mtpd (r0)+
mfpd (r0)
inc (sp)
2:
mtpd (r0)
mov (sp)+,r0
rti
1:
add $1,_pusertix
adc _pusertix+2
rti
.endif