mirror of
https://github.com/PDP-10/its.git
synced 2026-02-23 07:42:10 +00:00
1237 lines
27 KiB
Plaintext
1237 lines
27 KiB
Plaintext
;-*- midas -*-
|
||
|
||
subttl basic RWK UUO's
|
||
|
||
.qmtch==1
|
||
|
||
a=1 ;temporary
|
||
b=2 ;temporary
|
||
c=3 ;temporary
|
||
d=4
|
||
e=5
|
||
f=6
|
||
chr=10 ;character being read
|
||
ea=11 ;effective address of UUO's
|
||
opc=12 ;op code of UUO's
|
||
ac=13
|
||
u1=14 ;uuo temporary 1
|
||
u2=15 ;uuo temporary 2
|
||
u3=16 ;uuo temporary 3
|
||
sp=17 ;stack pointer
|
||
|
||
ifndef ttyp,ttyp==-1 ;assume we want the TTY opened
|
||
ifndef tyic,tyic==1 ;tty input channel
|
||
ifndef tyoc,tyoc==2 ;tty output channel
|
||
ifndef dski,dski==3 ;dsk output channel
|
||
ifndef dsko,dsko==4 ;dsk output channel
|
||
ifndef clic,clic==5 ;CLI output channel
|
||
ifndef usrc,usrc==7 ;user input and utility channel
|
||
ifndef uout,uout==10 ;usr output and fucked channel
|
||
ifndef ufdie,ufdie=0 ;needed early, so put it here
|
||
ifndef ufsiot,ufsiot=0 ;needed early, so put it here
|
||
|
||
|
||
opcode=.bp <777_33 0,0> ;opcode field
|
||
accum=.bp <0 17,0> ;accumulator field
|
||
index=.bp <0 0,(17)> ;index register
|
||
|
||
cnt==4000 ;control
|
||
cnti==5000 ;control immediate
|
||
errret==3000 ;error return
|
||
argi==1000 ;immediate argument
|
||
val==2000 ;value return
|
||
|
||
ifndef pdleng,[pdleng==50] ;length of PDL
|
||
ifndef patchl,[patchl==100] ;length of patch area
|
||
|
||
|
||
|
||
ifndef uuoloc,[uuoloc=100]
|
||
ifndef infuuo,[infuuo==0]
|
||
|
||
ifndef infuuo,infuuo==0
|
||
ifndef tyintp,tyintp==0
|
||
ifndef piclip,piclip==0
|
||
ifndef pirltp,pirltp==0
|
||
|
||
intp==infuuo\tyintp\piclip\pirltp
|
||
|
||
ifndef fgetp,fgetp==0 ;routine to read file names
|
||
|
||
;; here are the vars. for use with the load-check feature (ldchkp)
|
||
|
||
ifndef ldchkp,ldchkp==0 ;non-zero if we want load-check feature
|
||
|
||
ifn ldchkp,[
|
||
ifndef mvsldu,mvsldu==150. ;minimum fair share is 40%
|
||
ifndef mvsusr,mvsusr==18. ;maximum no. of users is 15.
|
||
ifndef usr$$$,usr$$$==20 ;charge per user
|
||
ifndef lod$$$,lod$$$==1
|
||
ifndef mvlmax,mvlmax==350. ;max points overall
|
||
]
|
||
|
||
;; interdependencies go here -- this must be LAST in the conditionals set-up
|
||
|
||
ifn infuuo,[ufdie==-1
|
||
ufsiot==-1
|
||
intp==-1
|
||
]
|
||
|
||
ifndef loss,loss=<.lose 1400>
|
||
|
||
|
||
;;The following two macros were swiped from the DRAGON. I retain comments...
|
||
;I HAVE IBM DISEASE
|
||
;FOLLOWING MACRO SAVES LOAC THROUGH HIGHAC INCLUSIVE ON PDL
|
||
;P MAY BE AMONG THOSE SAVED, BUT MUST BE NEITHER LOWAC NOR HIGHAC
|
||
;CLOBBERS LOWAC
|
||
|
||
DEFINE SAVE LOWAC,HIGHAC
|
||
PUSH sp,<LOWAC>
|
||
MOVSI <LOWAC>,<LOWAC>+1
|
||
HRRI <LOWAC>,1(sp)
|
||
ADD sp,[<HIGHAC>-<LOWAC>,,<HIGHAC>-<LOWAC>]
|
||
SKIPL sp
|
||
loss
|
||
BLT <LOWAC>,(sp)
|
||
TERMIN
|
||
|
||
;UNDO A SAVE (THIS IS WHY HIGHAC SHOULD NOT BE P)
|
||
|
||
DEFINE RESTOR LOWAC,HIGHAC
|
||
MOVSI <HIGHAC>,-<<HIGHAC>-<LOWAC>>(sp)
|
||
HRRI <HIGHAC>,<LOWAC>
|
||
BLT <HIGHAC>,<HIGHAC>
|
||
SUB sp,[<HIGHAC>-<LOWAC>+1,,<HIGHAC>-<LOWAC>+1]
|
||
TERMIN
|
||
|
||
|
||
define terpri chan=tyoc ;terpri on channel
|
||
tyo chan,[^M]
|
||
tyo chan,[^J]
|
||
termin
|
||
|
||
define text *string*
|
||
!.length |string|,,[asciz |string|]!termin
|
||
|
||
define ascnt *string*
|
||
![text /string/]!termin
|
||
|
||
define type *string*
|
||
sioto tyoc,<ascnt /string/>
|
||
termin
|
||
|
||
define death *string*
|
||
die <ascnt /string/>
|
||
termin
|
||
|
||
define print chan=tyoc,*string*
|
||
sioto chan,<ascnt /string/>
|
||
termin
|
||
|
||
define tabdef name
|
||
define name cruft
|
||
cruft
|
||
termin
|
||
|
||
define a!name more
|
||
name [define name cruft
|
||
cruft
|
||
more]
|
||
termin
|
||
termin
|
||
termin
|
||
|
||
|
||
|
||
define do stuff,else,\label
|
||
define ddoo exit
|
||
jrst [stuff
|
||
jrst label]
|
||
!else!
|
||
|
||
label::
|
||
termin
|
||
|
||
ddoo <jrst label>
|
||
|
||
termin
|
||
|
||
define do.lab cruft
|
||
cruft!!termin
|
||
|
||
define do.bod cruft
|
||
cruft!!termin
|
||
|
||
define adotab label,stuf
|
||
|
||
do.lab [define do.lab cruft
|
||
cruft]label!!termin
|
||
|
||
do.bod [define do.bod cruft
|
||
cruft]stuf!!termin
|
||
|
||
termin
|
||
|
||
define dotab
|
||
|
||
define foo fo1,fo2
|
||
irp x,,#[fo1],y,,#[fo2]
|
||
x: y
|
||
termin
|
||
termin
|
||
|
||
foo do.lab,do.bod
|
||
termin
|
||
|
||
|
||
define seval a,b ;get value of symbol B in A
|
||
move a,[squoze 0,/b/]
|
||
.eval a,
|
||
loss
|
||
termin
|
||
|
||
define eval a,b
|
||
seval a,b
|
||
hrl a,a ;move to left
|
||
hrri a,a ;destination is a
|
||
.getloc a, ;get it into a
|
||
termin ;done!
|
||
|
||
DEFINE SYSCAL A,B,C=<rwkuuo"calerr>
|
||
.CALL [SETZ ? SIXBIT/A/ ? B ? setz+<errret,,0>+c] TERMIN
|
||
|
||
|
||
call=pushj sp,
|
||
|
||
define ret
|
||
popj sp,
|
||
termin
|
||
|
||
define loop ix=0,beg,end,stuf,\label1,label2
|
||
define lloop exit
|
||
|
||
move ix,[beg-end,,beg]
|
||
label1::
|
||
stuf
|
||
aobjn ix,label1
|
||
label2::
|
||
termin
|
||
|
||
lloop [jrst label2]
|
||
termin
|
||
|
||
define prtval *prtstr,valstr
|
||
vlpr [<ascnt /prtstr/>,,[asciz /valstr/]]
|
||
termin
|
||
|
||
.begin rwkuuo ;My very own system calls!
|
||
|
||
tabdef utab
|
||
|
||
uuonum==1
|
||
|
||
define uuodef name,op,oper
|
||
ifndef uf!name,[uf!name==0]
|
||
ifn uf!name,{define uuodex [op1=[pushj sp,]]
|
||
autab [.m"name=<.-uuotab>_33
|
||
op1 u!name]
|
||
termin}
|
||
.also [ oper
|
||
uuodex op]
|
||
termin
|
||
|
||
|
||
|
||
|
||
loc 40
|
||
UUO: 0 ;traping UUO goes here.
|
||
JSR UUOH ;go handle UUO's
|
||
ifn intp, -intlng,,tsint ;abjon ptr to interrupt table
|
||
|
||
loc uuoloc
|
||
|
||
.m"intspc=100*100+5
|
||
ifn intp,[
|
||
tsint: .m"intspc,,sp
|
||
ifn tyintp,[0 ? 1_tyic ? 0 ? 0 ? ttyint]
|
||
ifn infuuo,[%piioc ? 0 ? 0 ? 0 ? ignore
|
||
0 ? -1,,0 ? 0 ? 0 ? rwkuuo"infuuo"dhandl]
|
||
ifn piclip,[%picli ? 0 ? 0 ? 0 ? cliget]
|
||
ifn pirltp,[%pirlt ? 0 ? %pirlt ? -1 ? realt] ;don't allow recursive
|
||
;real-time interrupts...if we get them we must
|
||
;be screwed
|
||
intlng==.-tsint
|
||
|
||
ignore:
|
||
ifn ufsioto,[ type /AGot an unknown IOC interrupt. Continuing
|
||
/]
|
||
|
||
disbye: syscal dismis,[cnti,,.m"intspc ;just go back to what you were doing
|
||
sp]
|
||
loss
|
||
|
||
.m"dismis=jrst disbye
|
||
|
||
|
||
]
|
||
|
||
|
||
uuoh: 0 ;saved PC
|
||
push sp,uuo ;and our UUO
|
||
push sp,uuoh ;save the PC
|
||
save ea,u3 ;save our AC's
|
||
ldb opc,[opcode uuo] ;get the opcode
|
||
cail opc,utabl ;is it legal?
|
||
ifn ufdie, die [text /BAD USER UUO/] ;nope
|
||
ife ufdie, .lose
|
||
ldb ac,[accum uuo] ;yep
|
||
hrrz ea,uuo ;get the effective address
|
||
xct uuotab(opc) ;and dispatch on it
|
||
restor ea,u3 ;restore our AC's
|
||
pop sp,uuoh ;restore UUOH
|
||
pop sp,uuo ;and restore our UUO -- We're done with this
|
||
;one. (hence if we die in a UUO the UUO is the
|
||
;last UUO done. Otherwise it is 0 (maybe might
|
||
;make it always last UUO, never reset to 0?
|
||
jrst @uuoh ;return
|
||
|
||
|
||
uuodef huh,jrst,[
|
||
uhuh: type /AType ? for list of commands.
|
||
/
|
||
move sp,[-pdleng,,pdl]
|
||
jrst @qitadr
|
||
QITADR: rwkend
|
||
]
|
||
uuodef usioti,,[
|
||
usioti: hrli u1,440700 ;ascii string pointer
|
||
hrr u1,(ea) ;get address of string
|
||
|
||
hlrz u2,(ea) ;get length of string
|
||
|
||
syscal siot,[ac ;ac has output channel
|
||
u1
|
||
u2]
|
||
loss ;lost.
|
||
|
||
popj sp, ;return
|
||
]
|
||
|
||
uuodef tyo,[
|
||
utyo: movei u2,1 ;preset length to 1
|
||
hrli u3,070700 ;ascii string pointer to last 7 bits
|
||
hrr u3,ea ;get the effective address
|
||
|
||
syscal siot,[ac ? u3 ? u2] ;do it
|
||
loss ;nope, lost somehow
|
||
|
||
ret
|
||
]
|
||
|
||
uuodef sioto,,[
|
||
usioto: hrli u1,440700 ;ascii string pointer
|
||
hrr u1,(ea) ;get address of string
|
||
|
||
hlrz u2,(ea) ;get length of string
|
||
movem u2,siotl ;move it to memory so it can be cleared
|
||
syscal siot,[ac ;ac has channel
|
||
u1
|
||
siotl]
|
||
loss ;lost.
|
||
|
||
popj sp, ;return
|
||
siotl: 0
|
||
]
|
||
|
||
uuodef tyi,,[
|
||
utyi: syscal iot,[ac ;ac has channel
|
||
(ea)] ;to loc pointed to by EA
|
||
loss ;lost
|
||
popj sp, ;return
|
||
|
||
]
|
||
|
||
uuodef vlpr,,[
|
||
prloc: 0
|
||
vlloc: 0
|
||
uvlpr: hlrz u1,(ea) ;get ptr to string to print
|
||
hrrz u2,(ea) ;and ptr to string to value
|
||
movem u1,prloc ;and save them
|
||
movem u2,vlloc
|
||
sioto tyoc,@prloc ;print it
|
||
.value @vlloc ; and value it
|
||
popj sp, ;and return if we ever get back
|
||
|
||
]
|
||
|
||
uuodef die,jrst,[
|
||
udie: caie ea,0 ;if typing
|
||
sioto tyoc,(ea) ; type it
|
||
skipe debug ;are we debuggin?
|
||
.value ;yes, just return
|
||
.logout 1,
|
||
loss ;how the hell did this happen?
|
||
]
|
||
|
||
uuodef jload,,[
|
||
ujload: hrlz u1,ea ;from <ea>
|
||
hrri u1,bload ;to BLOAD
|
||
blt u1,eload ;until ELOAD
|
||
syscal open,[cnti,,.uii ;open load file
|
||
argi,,dski ;on DSKI channel
|
||
dev
|
||
fn1
|
||
fn2
|
||
dir]
|
||
loss ;lost
|
||
|
||
syscal load,[argi,,%jself ;load self
|
||
argi,,dski ;from dsk
|
||
[0,,-1] ;all
|
||
]
|
||
loss
|
||
loss ;if we get here something lost!
|
||
|
||
BLOAD:
|
||
dev: 0
|
||
fn1: 0
|
||
fn2: 0
|
||
eload:
|
||
dir: 0
|
||
]
|
||
|
||
;; convert 6-bit to ascii. Input in AC, output by excecuting EA.
|
||
;; typical EA's are IDPB AC,[440700,,<loc>] and TYO TYOC,AC
|
||
|
||
|
||
uuodef 6toa,,[
|
||
U6toa: movei u3,6 ;for six bits
|
||
move u2,[440600,,(ac)] ;byte pointer into AC
|
||
|
||
u6toa1: ildb u1,u2 ;get the first byte
|
||
addi u1,40 ;make it ascii
|
||
|
||
push sp,(ac) ;save ac he gave us so we can use it as scource
|
||
movem u1,(ac) ;use it
|
||
xct ,(ea) ;and excecute his output instruction
|
||
pop sp,(ac) ;and get his AC back
|
||
|
||
sojn u3,u6toa1 ;and loop till done
|
||
|
||
ret ;and we're all done
|
||
]
|
||
|
||
uuodef rd6,,[
|
||
urd6:
|
||
uread6: movei u3,6 ;at most 6 of them
|
||
move u2,[440600,,(ac)] ;moved 6 bits at a time into our accumulator
|
||
setzm (ac) ;clear our given AC
|
||
|
||
;** NOTE ** U3, EA, AND AC ARE ILLEGAL AS AC FIELDS for this UUO
|
||
|
||
read6a: push sp,(ac) ;what we have so far
|
||
xct (ea) ;do it
|
||
move u1,(ac) ;get it into a know ac
|
||
pop sp,(ac) ;and get back our current val
|
||
|
||
cain u1,^Q ;if it's ^Q
|
||
jrst [xct (ea) ;get a new char
|
||
jrst read6b] ;and sneak it passed other tests
|
||
cain u1,^M ;if carraige return
|
||
jrst read6t ;we're all done
|
||
cain u1,^C ;same for ^C
|
||
jrst read6t
|
||
cain u1,"," ;same for ,
|
||
jrst read6t
|
||
cain u1,40 ;same for space
|
||
jrst read6t
|
||
skipn file6p ;are we reading for a file?
|
||
jrst read6b ; nope, go to it
|
||
cain u1,";" ; if it's a semi
|
||
jrst read6t
|
||
cain u1,":" ;or a :
|
||
jrst read6t ;we're all done
|
||
|
||
read6b: caige u1,140 ;if it's small
|
||
subi u1,40 ;convert it so numbers work out right
|
||
|
||
caile u3, ;if we're beyond, don't write it out
|
||
idpb u1,u2 ;and write it to our dest
|
||
|
||
skipe file6p ;if we're looking at file-names, find end char
|
||
do [sos u3 ;count em anyway
|
||
jrst read6a] ; don't give up
|
||
|
||
sojn u3,read6a ;and loop until done
|
||
setom t.char ;note that we ended from too many chars
|
||
ret ;and we're all done!
|
||
|
||
read6t: movem u1,t.char ;save our final char for posterity
|
||
ret ;and we're all done
|
||
|
||
file6p: 0 ;non-zero if we want : and ; to terminate 6bit
|
||
t.char:0 ;this gets the terminating character or -1 if
|
||
;it terminates because of going over 6 chars
|
||
]
|
||
|
||
;;; <ea> has an instruction to get the next character.
|
||
;;; the specified AC gets the result. the ea must put the char in the same
|
||
;;; ac as is being used for the result
|
||
;;; AC, EA, U2 may not be clobbered by the instruction
|
||
|
||
uuodef rda,,[
|
||
uread1: setzm (ac) ;clear our given ac
|
||
movei u2,12 ;get a 10
|
||
|
||
red10a: push sp,(ac) ;push what we have so far
|
||
xct (ea) ;and get next char
|
||
move u1,(ac) ;get it into a know ac
|
||
pop sp,(ac) ;restore our AC
|
||
|
||
caige u1,60 ;is it too small?
|
||
ret ; yes, we're at end, return
|
||
caile u1,71 ;is it too big?
|
||
ret ; yes, we're at end, return
|
||
|
||
imulm u2,(ac) ;and multiply the AC by it
|
||
subi u1,60 ;make it a number
|
||
addm u1,(ac) ;and add in our number
|
||
jrst red10a ;go get more
|
||
]
|
||
|
||
;; convert decimal to ascii. Input in AC, output by excecuting EA.
|
||
;; typical EA's are IDPB AC,[440700,,<loc>] and TYO TYOC,AC
|
||
|
||
uuodef deca,,[
|
||
|
||
udeca: move u1,(ac) ;get number in U1
|
||
|
||
decpnt: idivi u1,10. ;figure first digit
|
||
push sp,u2 ;push remainder
|
||
skipe u1 ;done?
|
||
pushj sp,decpnt ;no compute next one
|
||
|
||
decpn1: pop sp,u1 ;yes, take out in opposite order
|
||
addi u1,60 ;make ascii
|
||
push sp,(ac) ;save his AC so we can use it as output source
|
||
movem u1,(ac) ;use it
|
||
xct (ea) ;and execute his output instruction
|
||
pop sp,(ac) ;and give it back
|
||
popj sp, ;and return for the next one.
|
||
]
|
||
|
||
;;; Convert number to ascii rep of octal
|
||
;;; Take number in ac, ea has output instruction
|
||
|
||
uuodef 8toa,,[
|
||
|
||
u8toa: move u1,(ac) ;get number in U1
|
||
|
||
octpnt: idivi u1,10 ;figure first digit
|
||
push sp,u2 ;push remainder
|
||
skipe u1 ;done?
|
||
pushj sp,octpnt ;no compute next one
|
||
|
||
octpn1: pop sp,u1 ;yes, take out in opposite order
|
||
addi u1,60 ;make ascii
|
||
push sp,(ac) ;save his AC so we can use it as output source
|
||
movem u1,(ac) ;use it
|
||
xct ,(ea) ;and execute his output instruction
|
||
pop sp,(ac) ;and give it back
|
||
popj sp, ;and return for the next one.
|
||
]
|
||
|
||
uuodef rnd,,[
|
||
urnd: push sp,a ;generate a random number
|
||
push sp,b
|
||
push sp,c
|
||
|
||
eval a,jtmu ;get system resource word
|
||
add a,ooff ;add in an offset
|
||
add a,mtoop ;and our
|
||
and a,[377777,,-1] ;make positive
|
||
idiv a,mlen ;mod size of pointer fields?
|
||
hrlz b,b ;and put in left half
|
||
hrri b,b ;and get result in b
|
||
.getloc b, ;get that
|
||
add b,onum
|
||
and b,[377777,,-1] ;make positive
|
||
movem a,ooff ;save old one
|
||
eval a,nnsked ;number of times null job schedualed
|
||
;this should vary more when load light, to make
|
||
;up for others varying less
|
||
add b,a ;and include this in our randomness
|
||
idivi b,(ea) ;mod number of entries
|
||
movem b,onum ;save old one
|
||
movem c,rndloc ;return our value. Save it in RNDLOC for debug
|
||
pop sp,c
|
||
pop sp,b
|
||
pop sp,a
|
||
move u1,rndloc
|
||
movem u1,(ac) ;and return in right accumulator
|
||
ret
|
||
|
||
rndloc: 0
|
||
]
|
||
|
||
uuodef fget,,[
|
||
|
||
.m"dev: 'DSK '
|
||
.m"DIR: 'USERS '
|
||
.m"FN1: -1
|
||
.m"FN2: -1
|
||
|
||
|
||
ufget:
|
||
push sp,a
|
||
push sp,b
|
||
push sp,rwkuuo"file6p ;save for posterity
|
||
setom rwkuuo"file6p ;read it in file format
|
||
|
||
floop: XCT (EA) ;Get a name
|
||
|
||
;; typically EA is a [rd6 a,[tyi tyic,a]]
|
||
|
||
move b,rwkuuo"t.char6 ;get termination character
|
||
cain b,72 ; colon?
|
||
do [movem a,.m"dev ;note the device
|
||
jrst floop] ;and get more
|
||
cain b,40 ;is it a space?
|
||
do [movem a,.m"fn1 ;save it out
|
||
jrst floop] ;and go for more
|
||
|
||
cain b,73 ;is it a semicolon?
|
||
do [movem a,.m"dir ; save it
|
||
jrst floop] ;and go for more
|
||
jumpe a,fgot ;have we got it?
|
||
|
||
movem a,.m"fn2 ;save it out
|
||
fgot: pop sp,rwkuuo"file6p ;and restore our state
|
||
pop sp,b
|
||
pop sp,a
|
||
ret
|
||
]
|
||
|
||
|
||
.m"debug: 0 ;is in main block so user can reference
|
||
tyo1c: 1 ;will be reset to one on every tyo
|
||
calerr: 0 ;error return code
|
||
patch: block patchl ;patching area
|
||
|
||
pdl: [.status tyoc,a
|
||
ifn ufsiot,[skipn a,
|
||
type /PDL underflow/]
|
||
loss]
|
||
block pdleng ;PDL area
|
||
|
||
onum: 0
|
||
ooff: 0
|
||
mtoop: 0
|
||
mlen: 0
|
||
|
||
ifn infuuo,[
|
||
|
||
;;inferior hacking stuff
|
||
|
||
.begin infuuo
|
||
c1.cnt: %pival+%pic.z+%pibrk+%pidcl
|
||
c1.ded: %pi1pr+%pib42+%pipar
|
||
class2: %pitrp+%pifet+%pitty+%pidis+%piilo+%piioc+%pioob+%pimpv+%pimar
|
||
c1.2: %pi1pr+%pibrk+%pib42+%pipar+%pival+%pic.z+%pitrp+%pifet+%pitty+%pidis+%piilo+%piioc+%Pioob+%pimpv+%pimar+%pidcl
|
||
|
||
TTYFLG: 0 ;nonzero if we have given away our TTY
|
||
|
||
dhandl:.dtty ;get back the TTY
|
||
skip
|
||
syscal usrvar,[argi,,usrc ;get his interrupts
|
||
['PIRQC ']
|
||
val,,a]
|
||
loss
|
||
syscal usrvar,[argi,,usrc ;get mask for type 2 interrupts
|
||
['MASK ']
|
||
val,,b]
|
||
loss
|
||
and b,class2 ;b<-class two which are enabled
|
||
tdz a,b ;remove them from our interrupt word
|
||
and a,c1.2 ;remove class 3 interrupts
|
||
move b,a ;get a copy
|
||
tdz a,c1.cnt ;remove ones we'll handle
|
||
jumpn a,infuuo"fatal ;go handle fatal variety
|
||
trne b,%pibrk ;is the a .BREAK
|
||
jrst infuuo"break ;go handle
|
||
trne b,%pival ;is this a .VALUE?
|
||
jrst infuuo"value ;go handle
|
||
tdne b,[%pic.z+%pidcl] ;control-Z ?
|
||
skipa
|
||
jrst [type /ABug in Inferior Interrupt HandlerA/
|
||
loss]
|
||
syscal usrvar,[argi,,usrc ;reset his PIRQC
|
||
['APIRQC']
|
||
b]
|
||
loss
|
||
goback: syscal dismis,[cnti,,.m"intspc
|
||
sp
|
||
argi,,retloc]
|
||
loss
|
||
retloc: type /AReturned from InferiorA/
|
||
setzm ttyflg ;remember we have it back for good
|
||
ret
|
||
|
||
define usrmem usrc,dest,a,b
|
||
syscal corblk,[cnti,,%cbwrt ;may as well get write if we can
|
||
argi,,0 ;no XORing in my program!
|
||
argi,,%jself
|
||
argi,,377 ;mega moby page
|
||
argi,,usrc ;from usrc channel job
|
||
a] ;at location a
|
||
loss
|
||
move dest,(b)<377*2000> ;and get it
|
||
termin
|
||
|
||
define uread usrc,loc
|
||
.access usrc,loc
|
||
syscal iot,[argi,,usrc
|
||
loc]
|
||
loss
|
||
termin
|
||
|
||
define uwrite usrc,loc,dat
|
||
.access usrc,loc
|
||
syscal iot,[argi,,usrc
|
||
dat]
|
||
loss
|
||
termin
|
||
|
||
define addrup ind,rh,index,\foo,foo1
|
||
jumpe index,foo1 ;if non-zero index
|
||
uread usrc,index ;get value of index
|
||
add rh,index ;and add it in
|
||
foo1:: jumpn ind,[uread usrc,rh ;if we're indirecting
|
||
jrst foo] ;do the indirection
|
||
foo::
|
||
termin
|
||
|
||
define pagmak a
|
||
andi a,-1 ;clear left half
|
||
lshc a,-12 ;split off page number from rest
|
||
lsh <a+1>,12-44 ;and make remainder
|
||
termin
|
||
|
||
break: syscal usrvar,[argi,,usrc ;turn off the interrupt
|
||
['APIRQC']
|
||
[%pibrk]]
|
||
loss
|
||
syscal usrvar,[argi,,usrc ;get location of break
|
||
['UPC ']
|
||
val,,a]
|
||
loss
|
||
subi a,1 ;back up to the .BREAK
|
||
move e,a ;move to where we have two adjacent ac's
|
||
pagmak e ;a <- page#, f <- loc in page
|
||
usrmem usrc,a,e,f ;a <- contents of memory
|
||
ldb b,[accum a] ;b <- accumulator
|
||
ldb c,[index a] ;c <- index
|
||
hlr d,a ;clear d, getting left half of a
|
||
andi d,(@) ;and with indirect bit
|
||
andi a,-1 ;a <- address field
|
||
|
||
cain b,12 ;is it a .BREAK 12, ?
|
||
jrst brk12 ;yes
|
||
caie b,16 ;is it garbage?
|
||
jrst unbrk ;go handle unknown break
|
||
type /AInferior finishedA/
|
||
.uclose usrc, ;it must have been asking to die since we
|
||
;told it we wern't a DDT
|
||
jrst infdon
|
||
|
||
define .M"JCL *lcj*
|
||
move a,[text /lcj/]
|
||
movem a,rwkuuo"infuuo"jclptr
|
||
termin
|
||
|
||
jclptr: 0
|
||
|
||
brk12: addrup d,a,c ;ind,addr,ix
|
||
move e,a ;move to where we have room
|
||
move c,a ;and hold in C for error messages
|
||
pagmak e ;e <- page #, f <- loc in page
|
||
usrmem usrc,a,e,f ;get from his memory the location pointed to
|
||
jumpl a,[hlrz a,a ;if writing
|
||
caie a,400005 ; if clearing JCL
|
||
jrst [setzm jclptr ;clear it and
|
||
jrst infdon] ;be done
|
||
type /ABarf: Inferior trying to write!
|
||
/ ;complain
|
||
jrst infdon] ;and be done
|
||
hlrz b,a ;get operation
|
||
hrrz d,a ;and address
|
||
trne d,200000 ;is it block mode?
|
||
jrst [type /Barf: Inferior trying to use block mode .BREAK 12,
|
||
.BREAK 12,/
|
||
jrst addprt] ;go print out err message
|
||
cail b,brktbl ;is it out-of-range?
|
||
jrst unbrk1
|
||
xct brktb(b)
|
||
|
||
addprt: 8toa c,[tyo tyoc,c] ;type address
|
||
sioto tyoc,[text "/ "] ;"open" location with form
|
||
8toa b,[tyo tyoc,b] ;and type contents
|
||
type /,,/ ;in halfword mode
|
||
8toa d,[tyo tyoc,d] ;so we can read it easier
|
||
terpri tyoc ;CRLF
|
||
jrst infdon ;and give up
|
||
|
||
unbrk1: type /Barf: Inferior trying to use a .BREAK 12, I can't handle.
|
||
.BREAK 12,/
|
||
jrst addprt
|
||
|
||
brktb: jrst unbrk1
|
||
jrst unbrk1
|
||
jrst unbrk1
|
||
jrst symptr
|
||
jrst unbrk1
|
||
jrst getjcl
|
||
brktbl==.-brktb
|
||
|
||
symptr: caig d,17 ;is it an AC?
|
||
jrst [uwrite uout,d,[0] ;yep, do it the dangerous way
|
||
jrst infcnt]
|
||
move e,d ;get more space to work in and save d for error
|
||
pagmak e ;compute page in a and word in f
|
||
syscal corblk,[cnti,,%cbndw ;need write access
|
||
argi,,0
|
||
argi,,%jself
|
||
argi,,377
|
||
e]
|
||
jrst jclovf ;go gripe
|
||
add f,<377_22> ;make absolute in our space
|
||
setzm (f) ;and set the appropriate word to 0
|
||
jrst infcnt ;and continue
|
||
|
||
getjcl: move e,d ;get more space and save d for error
|
||
pagmak e
|
||
syscal corblk,[cnti,,%cbndw ;need write access
|
||
argi,,0 ;no XORing, please
|
||
argi,,%jself ;map into ourself
|
||
argi,,376 ;at the highest possible location
|
||
argi,,usrc ;our inferior's
|
||
e] ;page which is contained in A
|
||
jrst jclovf
|
||
aos e ;get next page too
|
||
hlrz a,jclptr ;get length pointer of JCL
|
||
addi a,4
|
||
idivi a,5 ;(ptr+4)/5==length in words
|
||
add a,f ;the final loc
|
||
cail a,2000 ;overflow?
|
||
jrst [syscal corblk,[cnti,,%cbndw ;need writing
|
||
argi,,0 ;barf, no XOR, please
|
||
argi,,%jself
|
||
argi,,377 ;very moby
|
||
argi,,usrc ;our very inferior inferior
|
||
e] ;and the next page
|
||
jrst jclovf ;complain of indigestion
|
||
jrst jcljcl] ;go write JCL
|
||
|
||
;a -- absolute ending address
|
||
;b -- operation
|
||
;c -- effective address of .BREAK
|
||
;d -- right half of contents of ea of .break
|
||
;e -- page number in inferior of JCL buffer
|
||
;f -- loc in that page
|
||
|
||
jcljcl: addi a,<376_12> ;make end addr. point into our page map
|
||
addi f,<376_12> ;make the dest. address point into our map
|
||
hrr e,f ;and put in right half for blt
|
||
hrl e,jclptr ;get our source for the BLT from the JCLPTR
|
||
blt e,-1(a) ;and perform the transfer
|
||
skipe ttyflg ;if it had the tty
|
||
jrst infcnt
|
||
jrst infdon ;else just dismiss
|
||
|
||
infcnt: setom ttyflg ;remember where the TTY went
|
||
.atty usrc, ;give it to him
|
||
jrst [.dtty ;get it back
|
||
.atty usrc, ;and try again
|
||
loss ;nope, we're screwed somehow
|
||
jrst infcn1] ;good, one with the show
|
||
|
||
call start
|
||
|
||
infcn1: syscal dismis,[cnti,,.m"intspc
|
||
sp]
|
||
loss
|
||
|
||
jclovf: type /AInferior tried to read into pure or non-existant memory
|
||
.BREAK 12,/
|
||
jrst addprt ;tell him about loss
|
||
|
||
unbrk: type /Inferior gave an unknown .BREAK
|
||
.BREAK /
|
||
|
||
addrtp: 8toa b,[tyo tyoc,b] ;type out the address stuff
|
||
tyo tyoc,[","] ;type out the comma
|
||
caie d,0 ;indirect?
|
||
tyo tyoc,["@"] ;type it
|
||
|
||
caie a,0 ;rh nonzero?
|
||
8toa a,[tyo tyoc,a]
|
||
|
||
jumpn c,[tyo tyoc,["("] ;type the (
|
||
8toa c,[tyo tyoc,c] ;type the index
|
||
tyo tyoc,[")"]
|
||
jrst ubrk1]
|
||
|
||
ubrk1: type / >>> /
|
||
addrup d,a,c ;compute effective address
|
||
8toa a,[tyo tyoc,a] ;and print it
|
||
terpri tyoc
|
||
jrst infdon
|
||
|
||
value: syscal usrvar,[argi,,usrc ;turn off the interrupt
|
||
['APIRQC']
|
||
[%PIVAL]]
|
||
loss
|
||
type /AInferior .VALUE'd....I don't understand that so I'm continuingA/
|
||
jrst infdon
|
||
|
||
fatal: type /Ainferior got a fatal interruptA/
|
||
.uclose usrc,
|
||
jrst infdon
|
||
|
||
infdon: setzm ttyflg ;remember we have it back for good
|
||
syscal dismis,[cnti,,.m"intspc
|
||
sp]
|
||
loss
|
||
|
||
start: syscal usrvar,[argi,,usrc ;copy his old state
|
||
['OPTION']
|
||
val,,a]
|
||
loss
|
||
tlz a,optcmd+optbrk ;clear the OPTCMD bit (+ the OPTBRK since LISP
|
||
;demands it!)
|
||
skipe jclptr ;if there is JCL
|
||
tlo a,optcmd+optbrk ;set it again
|
||
syscal usrvar,[argi,,usrc ;and set it up
|
||
['OPTION']
|
||
a] ;write it back again
|
||
loss
|
||
|
||
syscal usrvar,[argi,,usrc ;GO!
|
||
['USTP ']
|
||
argi,,0]
|
||
loss
|
||
|
||
ret
|
||
|
||
.m"TTYGO:
|
||
call start
|
||
setom ttyflg ;remember we gave it away
|
||
.atty usrc, ;give up the TTY and wait for return
|
||
skipe ttyflg ;what?
|
||
.hang ;until return of TTY
|
||
.dtty ;make SURE that we have the TTY
|
||
ret
|
||
ret
|
||
|
||
.M"nttygo:
|
||
syscal usrvar,[argi,,usrc
|
||
['USTP ']
|
||
argi,,0]
|
||
loss
|
||
ret
|
||
|
||
myunam: 0
|
||
ifndef .m"usrc,.m"usrc==7
|
||
istrt: 0
|
||
|
||
define .m"infcr chan,name,fn1,fn2,sname,f.loss=loss,page=-1,handle=.m"rwkuuo"infuuo"dhandl
|
||
push sp,a ;save a for local use
|
||
.status usrc,a ;look at the channel
|
||
caie a,0 ;if there is nothing open
|
||
.uclose usrc, ;kill it
|
||
|
||
syscal open,[cnti,,0 ;create a job
|
||
argi,,usrc
|
||
['USR ']
|
||
rwkuuo"infuuo"myunam
|
||
[sixbit /name/]]
|
||
loss
|
||
syscal open,[cnti,,.uio ;and an output channel to it (ugh!)
|
||
argi,,uout
|
||
['USR ']
|
||
rwkuuo"infuuo"myuname
|
||
[sixbit /name/]]
|
||
loss
|
||
|
||
syscal open,[cnti,,.uii ;open a file to load into it
|
||
argi,,dski
|
||
[sixbit /DSK /]
|
||
[sixbit /FN1/]
|
||
[sixbit /FN2/]
|
||
[sixbit /SNAME/]]
|
||
f.loss
|
||
|
||
syscal load,[argi,,usrc ;load it
|
||
argi,,dski]
|
||
loss
|
||
|
||
syscal iot,[argi,,dski ;get starting address
|
||
argi,,a] ;in a
|
||
loss
|
||
andi a,-1 ;ignore the JRST part
|
||
|
||
syscal close,[argi,,dski] ;close it
|
||
loss
|
||
|
||
movem a,rwkuuo"infuuo"istrt ;and save the ADDR in ISTRT
|
||
|
||
syscal usrvar,[argi,,usrc ;make it start there
|
||
['UPC ']
|
||
a] ;a has address
|
||
loss
|
||
|
||
syscal usrvar,[argi,,usrc ;get what bit to enable
|
||
['INTB ']
|
||
val,,a]
|
||
loss
|
||
|
||
syscal usrvar,[argi,,%jself ;and enable it
|
||
['IMSK2 ']
|
||
a]
|
||
loss
|
||
pop sp,a
|
||
|
||
termin
|
||
.m"infkil:
|
||
push sp,a ;get A free
|
||
.status usrc,a ;is there an inferior?
|
||
jumpe a,[type /AThere is no inferior open.A/
|
||
pop sp,a ;restore A
|
||
ret] ;and give up.
|
||
pop sp,a ;restoer a
|
||
setzm ttyflg ;remember we have it back for good
|
||
.uclose usrc, ;kill it
|
||
type /AInferior KilledA/ ;say it
|
||
ret ;return
|
||
|
||
.end infuuo
|
||
]
|
||
|
||
uuotab: loss
|
||
utab
|
||
utabl==.-uuotab
|
||
consta ;dump out constants table
|
||
|
||
popj.1: aos (sp) ;increment return address
|
||
popj sp, ;and return
|
||
.m"popj1=jrst popj.1 ;and define our symbol
|
||
|
||
ifn fgetp,[
|
||
|
||
.m"dev: 'DSK '
|
||
.m"DIR: 'USERS '
|
||
.m"FN1: -1
|
||
.m"FN2: -1
|
||
|
||
|
||
.m"fget:
|
||
push sp,a
|
||
push sp,b
|
||
push sp,rwkuuo"file6p ;save for posterity
|
||
setom rwkuuo"file6p ;read it in file format
|
||
floop: rd6 a,[tyi tyic,a] ;read in the name
|
||
|
||
move b,rwkuuo"t.char6 ;get termination character
|
||
cain b,72 ; colon?
|
||
do [movem a,.m"dev ;note the device
|
||
jrst floop] ;and get more
|
||
cain b,40 ;is it a space?
|
||
do [movem a,.m"fn1 ;save it out
|
||
jrst floop] ;and go for more
|
||
|
||
cain b,73 ;is it a semicolon?
|
||
do [movem a,.m"dir ; save it
|
||
jrst floop] ;and go for more
|
||
jumpe a,fgot ;have we got it?
|
||
|
||
movem a,.m"fn2 ;save it out
|
||
fgot: pop sp,rwkuuo"file6p ;and restore our state
|
||
pop sp,b
|
||
pop sp,a
|
||
ret
|
||
]
|
||
ifn ldchkp,[
|
||
.m"%sllog==1 ;bit to indicate not-logged-in
|
||
.m"%sldil==2 ;bit to indicate coming in from a dialup line
|
||
.m"%sload==4 ;bit to indicate over-stepping a load boundary
|
||
.m"%slcls==10 ;bit to indicate closed
|
||
.m"%sldet==20 ;we've been detached
|
||
|
||
.m"loadch: ;a routine to check the system load
|
||
;right half of A gets load units
|
||
;left half gets flags for dialup lines,
|
||
;detached tree, or not logged in
|
||
|
||
push sp,b ;save our temporaries
|
||
push sp,c
|
||
push sp,e
|
||
|
||
setz a, ;clear a to receive our results
|
||
|
||
.suset [.runame,,uname] ;check our UNAME....
|
||
hllz e,uname ;look at left half of uname for '___'
|
||
camn e,[-1,,0] ;are we logged in?
|
||
tlo a,%SLLOG ;no, note the fact
|
||
|
||
.suset [.rcnsl,,ttynum] ;we have to check for detached or dialups
|
||
move e,ttynum ;get our tty num
|
||
caig e, ;do we have one?
|
||
tlo a,%SLDET ;no, note the fact
|
||
|
||
movei b,1 ;let's figure out which we are
|
||
lsh b,(e) ;as a bit in the word
|
||
tdne b,dilmsk ;are we a dialup?
|
||
tlo a,%SLDIL ;yes, note the fact
|
||
|
||
;; charge for FAIR SHARE
|
||
|
||
eval e,SLOADU ;Get inverse fair share
|
||
subi e,100 ;shrink it down (it never gets below 100, I
|
||
;believe...)
|
||
move b,.M"mxsldu ;if not low enough
|
||
|
||
movei c,(e) ;get copy to work with
|
||
subi c,(b) ;subtract out the maximum
|
||
caile c, ;still OK?
|
||
call lcalc ;nope, gotta charge extra and set a bit
|
||
|
||
imul e,.m"lodchg ;compute the charge
|
||
add a,e ;add it in
|
||
|
||
;; charge for LUSERS
|
||
|
||
eval e,SUSRS ;Load also depends on how many users
|
||
move b,.M"MXSUSR ;if we're over our limit,
|
||
|
||
movei c,(e) ;get a copy of our limit to work on
|
||
subi c,(b) ;subtract out the actual
|
||
caile c, ;still OK?
|
||
call lcalc ;do the calculations and set the bit
|
||
|
||
imul e,.m"usrchg ;compute the charge
|
||
add a,e ;add it in
|
||
|
||
.rtime e, ;get time
|
||
camge e,t.open ;if before 8:00 am
|
||
jrst oopen ;it's OK
|
||
camle e,t.clos ;if it's after 8:00 pm
|
||
jrst oopen ;it's OK
|
||
|
||
.ryear b, ;get date stuff
|
||
ldb e,[.bp (003400),b] ;this byte
|
||
cain e,0 ;if zero
|
||
jrst oopen ;it's SUNDAY, let him go.
|
||
cain e,6 ;if not SATURDAY
|
||
jrst oopen ;OK!
|
||
call holdyp ;is it a holiday?
|
||
jrst nopen ; tell him we're closed!
|
||
|
||
oopen::
|
||
gobak: hrrz b,a ;get our points (separate from bits)
|
||
caml b,mxlmax ;OK! (or IS it....check out the total points)
|
||
tlo a,%SLOAD ;too high......note the fact
|
||
pop sp,e ;restore our AC's
|
||
pop sp,c
|
||
pop sp,b
|
||
ret ;and return it
|
||
|
||
nopen: tlo a,%SLCLS
|
||
jrst gobak
|
||
|
||
lcalc: tlo a,%SLOAD ;no, note the fact we're over
|
||
imuli c,10000 ;scale up the quantity
|
||
idivi c,(b) ;fraction more than max
|
||
addi c,10000 ;+ 1
|
||
imuli e,(c) ;times the total quantity
|
||
idivi e,10000 ;and scale back down
|
||
ret
|
||
|
||
holdyp: movsi e,-hldys ;aobjn ptr
|
||
.rdate b, ;get the year
|
||
|
||
holdy1: camn b,(e)hldy ;is it a holiday?
|
||
popj1 ;yes, skip
|
||
aobjn e,holdy1 ;no, loop?
|
||
ret ;no, not a holiday
|
||
|
||
hldy: '780417' ;Patriot's Day
|
||
'780530' ;Memorial Day
|
||
'780704' ;Independence Day
|
||
'781225' ;Christmas
|
||
'790101' ;New Year's Day
|
||
|
||
hldys==.-hldy
|
||
|
||
t.open: sixbit /080000/ ;opening time
|
||
t.clos: sixbit /200000/ ;closing time
|
||
|
||
|
||
|
||
.m"MXSLDU: MVSLDU ;Fair share less than 100/MVSLDU*100% means
|
||
;system is heavily loaded
|
||
.m"MXSUSR: MVSUSR ;More than MVSUSR users means system is heavily
|
||
;loaded
|
||
|
||
.m"MXLMAX: MVLMAX ;trip point for point total
|
||
|
||
.m"usrchg: usr$$$ ;how much to charge for users in load figure
|
||
.m"lodchg: lod$$$ ;how much to charge for system load in load
|
||
;figure
|
||
|
||
uname: 0 ;save the UNAME here to check for login etc.
|
||
dilmsk: 1_4+1_5+1_6+1_7
|
||
ttynum: 0 ;save our TTY number here to check for dialup
|
||
]
|
||
.m"go: move sp,[-pdleng,,pdl]
|
||
ifn ttyp,[syscal open,[cnti,,.uii
|
||
argi,,tyic
|
||
[sixbit /TTY/]]
|
||
loss
|
||
syscal open,[cnti,,<.uao+%tjdis>
|
||
argi,,tyoc
|
||
[sixbit /TTY/]]
|
||
loss
|
||
]
|
||
|
||
ifn infuuo,[
|
||
.suset [.runame,,rwkuuo"infuuo"myunam] ;get our name
|
||
]
|
||
|
||
ifn intp,[.suset [.roption,,a] ;get current .OPTION var
|
||
ior a,[(optint+optopc)]
|
||
.suset [.soption,,a] ;and set it for new interrupts and back up pc
|
||
syscal usrvar,[argi,,%jself ;enable IOC errors to ignored them
|
||
['IMASK ']
|
||
[%piioc]]
|
||
loss
|
||
]
|
||
ifn ufrnd,[
|
||
move a,[squoze 0,/toop/] ;output buffer pointers
|
||
.eval a,
|
||
loss
|
||
movem a,mtoop ;and save
|
||
move a,[squoze 0,/tintp/];end of output pointers, slower moving inpointr
|
||
.eval a,
|
||
loss
|
||
sub a,mtoop ;and save length of that region
|
||
movem a,mlen ;in mleng
|
||
]
|
||
|
||
.m"RWKEND==.
|
||
.end rwkuuo
|
||
|
||
;;and the rest of the system goes here.
|
||
|
||
|