|
|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 115968 (0x1c500)
Types: TextFile
Names: »mcentral «
└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer
└─⟦2ba378e4a⟧
└─⟦this⟧ »mcentral «
\f
m. moncentral - monitor central logic 17.0 beta
;--------------------------------------------------------------------------
; REVISION HISTORY
;--------------------------------------------------------------------------
; DATE TIME OR INIT DESCRIPTION
; RELEASE
;--------------------------------------------------------------------------
;88.03.24 R14.1A HSI start of description
;88.03.24 14.53 hsi insert ap procedure (d4)
; 18.30 hsi addr 138: max number of processors
; initialized at power up
;88.04.19 15.0 tsh c45, c46 rewritten and c47 added
;88.04.24 14.24 hsi addr 138 count instead value in monitor call
;88.04.24 11.16 kak io-test change in decrease stopcount (x2+8 --> x2+a138+1)
;88.05.09 10.05 kak w1=main at c45 and c46 before test
; 14.33 kak at return from c45 check-result in w0 instead of w2
;88.05.24 07.50 kak change of cpa and address base included
;88 05 30 10.59 hsi define global constants in monitor table
;88 06 01 09.15 hsi add constants to table
;88 06 02 07.00 tsh updates of c45 and c47 due to protocol changes
;88 06 16 11.12 kak function table at 'check itc function' extended
;88 08 16 13.32 hsi update constant table
;88 08 17 17.45 hsi add new function: stop normal communication
;88 09 12 13.54 d132: answer to removed link: use driverproc
;88 09 16 16.36 update constant table
;88 09 19 11.37 hsi move constant table to hw addr 160
;88 10 06 13.07 hsi error in calculate hw (c47) (R15)
;88 10 13 13.55 kak queue in ioc/lan main is checked after answer device and
; deliver interrupt
;88 11 21 13.39 kak bit 12-14 in message buffer state field is used to result or
; a disjunction of results (chained operations)
; and the final result is extracted from this field
;88 12 06 15.36 kak only the first status from chained operations are used
;89 01 23 12.53 kak deactivate process after program error (c2)
;89 03 08 09.09 kak no check of waiting operation to mainprocesses after deliver interrupt to driverproc,
; the check is performed when driverproc has token care of the interrupt
;89 03 15 15.10 kak decrease number of outstanding operation is delayed until answer device operation (c47)
; or after deliver interrupt to driver (c48), in the last case the main process
; is removed from the timer queue before the interrupt is delivered
;89 03 20 10.36 kak it is checked that clock process is not in queue before the clockinterrupt is delivered
;89 04 03 20.44 hsi error in c5: set process in running after error
;89 05 25 14.10 kak call of deliver answer changed: result must not be set in receiver field, but kept in w0
;--------------------------------------------------------------------------
;90 05 10 09.36 kak release 17.0
;90 05 10 09.37 kak new test point (41) at deliver interrupt to itc-main (c48)
;90 05 29 14.37 kak errorlog called at ioc and lan errors
; special watched receiver introducted for ioc and lan devices
b.i30 w.
i0=91 02 01
i1=09 36 00
; if newtime (i0,i1) > oldtime (a133,a134) then oldtime:=newtime;
c.i0-a133
c.i0-a133-1, a133=i0, a134=i1, z.
c.i1-a134-1, a134=i1, z.
z.
i10=i0, i20=i1
i15=i10/100000 , i10=i10-i15*100000 , i25=i20/100000 , i20=i20-i25*100000
i14=i10/10000 , i10=i10-i14*10000 , i24=i20/10000 , i20=i20-i24*10000
i13=i10/1000 , i10=i10-i13*1000 , i23=i20/1000 , i20=i20-i23*1000
i12=i10/100 , i10=i10-i12*100 , i22=i20/100 , i20=i20-i22*100
i11=i10/10 , i10=i10-i11*10 , i21=i20/10 , i20=i20-i21*10
i2: <: date :>
(:i15+48:)<16+(:i14+48:)<8+46
(:i13+48:)<16+(:i12+48:)<8+46
(:i11+48:)<16+(:i10+48:)<8+32
(:i25+48:)<16+(:i24+48:)<8+46
(:i23+48:)<16+(:i22+48:)<8+46
(:i21+48:)<16+(:i20+48:)<8+ 0
i3: al. w0 i2. ; write date:
rs w0 x2+0 ; first free:=start(text);
al w2 0 ;
jl x3 ; return to slang(status ok);
jl. i3. ;
e.
j.
\f
; segment 1 : enter monitor after load
; the monitor is entered in word 8. the words +2,+4 must at entry contain -
; +2 load flag, writetext
; +4 medium
; where
; load flag: 1 autoload of device controllers
; 0 no autoload
s. i3
w.
i0: i2. ; length of segment 1
0 ; init cat switch: writetext
i1: 0 ; init cat switch: medium
; entry from autoloader:
al. w3 i0. ; calculate top address of
rl w2 x3 ; last segment;
wa w3 4 ;
ds. w3 i3. ; ---------
se w2 0 ; (i.e. until segment size = 0)
jl. -8 ; -6
al. w2 i2. ; insert start address of segment 2;
dl. w1 i1. ; get init cat switches
jd x3-2 ; jump to segment 10
0,
i3:0 ; -----------
i2: ; first word of segment 2
; exit with:
; w0, w1 = init cat switches
; w2 = start address of segment 2
e. ; end segment 1
b. v100, r28, l60, g70, f30, e70, d160, c200
\f
; segment 2: monitor
s. k = 8, j0
w.b127=k, j0, k=k-2
; segment structure:
; monitor table (b names)
; interrupt response (c names)
; utility procedures (d names)
; monitor procedures (e names)
; name table (f names)
; process descriptions (f names)
; buffers (f names)
; ITC functions (l names)
; ITC states (l names)
;
; (g and h i and j names are used locally)
; monitor table
; all addresses are absolute addresses
; an integer after the semicolon means, that the address can't
; be changed, because it - unfortunately - has been published
; or because they have a hardware-function
b65: 0-0-0 ; 8: base of controller description table
b66: c25 ; 10: power up entry
b67: 0-0-0 ; first controller table entry
b68: 0-0-0 ; top controller table entry
b69: b69 ; queue head: software timeout
b69 ; (for devices)
b70: 0 , 0 ; time when last inspected
b72: 0-0-0 ; b53 ; start of interrupt table
b73: 0-0-0 ; b54 ; max external interrupt number
b0: 0-0-0 ; b53 - b16 ; (relative start of interrupt table
b74: a198 ; device address of i/o cpu
b75: 0 ; after powerfail (0==false, else true)
b18: 0 ; current buffer address
b19: 0 ; current receiver
b20: c96 ; address of simple wait event procedure
b21: 0-0-0 ; process description address of driverpoc
b101:0 ; return from subprocs
b102:0-0-0 ; a66 ; start of table(subproc-drivers)
b103:0 ; address of entry for send message for linkdriver areas
b76: 0 ; start of secondary interrupt chain
b30: 0-0-0 ; errorlog proc
b31: g66 ; errorlog entry
b58: 0 ; 54: device address register (used by ifp)
b59: 0-0-0 ; pu-information table address
b38: 0-0-0 ; rtc-table address
r. (:64-k+2:) > 1 ; 60-62 reserved for testprograms
a135<12+a136 ; 64: release, version of monitor
b42: -1000000 ; 66: current process (single cpu)
b2: b2 ; time slice queue head: next process
b2 ; last process
b3: 0-0-0 ; 72: name table start
b4: 0-0-0 ; 74: first device in name table
b5: 0-0-0 ; 76: first area in name table
b6: 0-0-0 ; 78: first internal in name table
b7: 0-0-0 ; 80: name table end
b8: b8 ; mess buf pool queue head: next buf
b8 ; last buf
0-0-0 ; 86: first byte of mess buf pool area
0-0-0 ; 88: last byte of mess buf pool area;( last word of last monitor table)
a6 ; 90: size of message buffer
b22: 0-0-0 ; 92: first drum chain in name table
b23: 0-0-0 ; 94: first disc chain in name table
b24: 0-0-0 ; 96: chain end in name table
b25: 0 ; 98: main cat chain table
b1: 0-0-0 ;cur process in monitor
b10: a85 ; maximum time slice
b11: 0 ;104: time slice (of current process)
0 ;106: zero (earlier: micro seconds)
b13: 0 , 0 ;108:110: time (unit of 0.1 milli seconds)
b14: 0 ; last sensed clock value
b9: 0-0-0 ; pu kind offset
b12: 0-0-0 ;116: number of storage bytes
a111<12 + a109 ;118: min global key, min aux cat key ?????
b15: 0 , 0 ; clockchange, after set clock:
; newtime - oldtime
b79: 0-0-0 ; interrupt statistical table (init in tabinit)
b81: b80 ; monitor call statistical table
b82: 0 ; current number of processors
b83: 0, 0, 0, 0 ; rescedule counter
r. (:160-k+2:) > 1; start of constant table:
b200: 0 , 0 ; double nul
b201: 1
b202: 2
b203: 3
b204: 4
b205: 5
b206: 6
b207: 7
b208: 8
b209: 9
b210:10
b211: 8.00030000 ; format identifier (in SSP/clock interrupt word)
b212: 8.37777777 ; last 23 bits
b213: 8.77777776 ; first 23 bits
b214: 8.00017777 ; last 13 bits
b215: 8.00007777 ; last hw
b216: 8.00003777 ; last 11 bits
b217: 8.77770000 ; first hw
b218: 8.77600000 ; first byte
b219: 8.00177400 ; midt byte
b220: 8.00000377 ; last byte
b235: 8.77777400 ; first tree byte
b236: 8.77777777 ; full house
b221: 512 ;
b222: 768
b223: 1<12
b224: 1<13
b225: 1<14
b226: 1<15
b227: 1<16
b228: 1<17
b229: 1<18
b230: 1<19
b231: 1<20
b232: 1<21
b233: 1<22
b234: 1<23
b237: 8.00177777
;redefinition of old constants
g48 = b203
g49 = b234
g50 = b213
g51 = b217
g52 = b215
g53 = b220
g62 = b229
g63 = b201
g65 = b212
g67 = b216
g68 = b214
b26 = b5 ; use area proceses as pseudo processes
l50 = (:a80>16a.1:)-1 ; ida/ifp device driver included (not used anymore)
l53 = (:a84>16a.1:)-1 ; ida/ifp device driver testoutput 0=yes, -1=no
; Sending a message to the main process the test mask may set, the mask contain 48 bit,
; default bit 45 and 46 and 47 are set, the meaning of the bits are:
; no procedure output no of hw
; 1: area driver part 1 message 18
; 2: area driver part 2 message 18
; 3: area driver part 2 message state 2
; 6: disc driver part 1 message 18
; 7: disc driver part 2 message 18
; 8: disc driver part 2 message state 2
; 11: tape driver part 1 message 18
; 12: tape+printer+gsd driver part 2 message 18
; 13: tape+printer+gsd driver part 2 message state 2
; 16: main driver part 2 message 18
; 17: main driver part 2 message state 2
; 24: tape+printer+gsd driver part 1 message 18
; 25: csp terminal driver part 1 message 18
; 26: csp terminal driver part 2 message 18
; 40: special set up reserve and
; release process ext proc 14
; 41: interrupt, supervisor message comm. area 24
; 45: interrupt buffer addr. 2
; 46: start controller comm. area 24
; 47: interrupt comm. area 24
c.(:a399>23a.1:)-1
; definition of dump area used in prepare dump (only RC9000-model 10)
0 ; lower dump area: first address
b27: 0 ; lower dump area: no of segments
0 ; upper dump area: first address
b28: 0 ; upper dump area: no of segments
z.
; definition of general registers in rc8000
b90 = 8.14 * 2 ; ilevc : interrupt level limit copy
b91 = 8.15 * 2 ; inf : current interrupt stack element address
b92 = 8.17 * 2 ; size : top available core address
b93 = 8.20 * 2 ; montop : 1 < 11 - top monitor procedure number
b94 = 8.62 * 2 ; clock
b95 = 8.57 * 2 ; ir : used to clear selected bits in interrupt reg
b96 = 8.04 * 2 ; status : cpu status register
b97 = 8.60 * 2 ; dswr : data swithes
b98 = 8.61 * 2 ; regsel : register swithes
b99 = 8.60 * 2 ; display
;
b100= 8.21*2 ; cpukind: 0: /45
; -1: /15, /25, /35
; 50: /50
; 55: /55
; 60: /60
; 65: /65
; the following registers are only defined in a mp:
b104= 8.24*2 ; cur process register
b105= 8.26*2 ; pu table register
b106= 8.27*2 ; exception offset register
b107= 8.30*2 ; dump offset register
b108= 8.25*2 ; pu index register
; definition of interrupt stack.
; parameters are relative to base of stack element (i.e. 1,3,5,..)
b.j0
j0=-1 , j0=j0+2 ; base of stack element
a326=j0 , j0=j0+2 ; regdump
a327=j0 , j0=j0+2 ; exception routine
a328=j0 , j0=j0+2 ; escape routine
a329=j0 , j0=j0+2 ; monitor call entry
a330=j0 , j0=j0+2 ; external interrupt entry
a331=j0 , j0=j0+2 ; interrupt limits, disabled/enabled
a325=j0-a326 ; size of interrupt stack element
e.
; parameter errors in monitor call:
;
; all monitor procedures check that the parameters are
; within certain limits.
; if the parameters are wrong, the calling process is break'ed.
;
; (all regs irrellevant)
c29: jl. (+2) ; goto internal break
c28 ;
; interrupt return:
; a new internal process may have been put up in front of
; the time slice queue, due to an external interrupt, or because
; the current monitor call was 'send message' or the like.
; therefore it must be tested, that the current process is still
; the one in front. if not: select that one.
b. i2, j0 w.
c99: ; interrupt return:
b. h1 w. ; if mp then
am (b9) ;
h0=k
jl. 0 ; begin
jl c24 ; goto mp activation
c.(:h0+a8-k-1:)
am 0, r.(: h0+a8+2-k :)>1 ; fill up
z.
e. ; end mp
rl w1 b1 ; proc := cur
sh w1 0 ; if cur defined and
jl. i0. ;
zl w0 x1+a13 ; proc.state <> running then
sn w0 a94 ; begin
ri a179 ;
i0: jl. w3 d8. ; activate process
rs w1 b42 ;
rs w1 b51 ; cur:= proc
rs w1 b1 ; cur process in monitor := proc;
al w2 x1 ;
gg w3 b91 ; w3 := inf (= address of current stack element);
dl w1 x2+a170 ; move: user escape address (cur)
; user exception address (cur)
ds w1 x3+a325+a328;
al w0 x2+a28 ; address of regdump area (cur)
rs w0 x3+a325+a326; to: previous interrupt stack element;
ri a179 ; return interrupt;
c24: rl w2 b2 ; proc:=first in queue ; activated:=true
al w1 x2-a16 ;
se w2 b2 ; do while queue not empty and activated
jl w3 d4 ; activate process; 88.03.24 14.53
ri 1 ; return to user;
jl. w3 d8. ;
rl w3 b82 ; if no of cpues = 1 then
sn w3 1 ; cur process := proc;
rs w1 b42 ;
jl c24 ; endwhile
; end
; return
e.
; procedure check itc function
;
;
; call
;
; w0 -
; w1 -
; w2 - (8000 special: main + a241)
; w3 -
;
b. i10, j21 w.
c45: ; procedure check_itc_function
; begin
c.l53 b. f4 w. ; ****** test 47 ******
rs. w3 f1. ;
al w1 x2-a241 ;
rs. w1 f0. ;
jl. w3 (f3.) ;
47 ;
f0: 0 ; main
f1: 0 ;
jl. f2. ;
al w0 x1+a500 ; dump main.communication area
al w1 x1+a517 ;
jl. w3 (f4.) ;
jl. f2. ;
f3: d150 ;
f4: d151 ;
f2: ;
e.z. ; ****** end test 47 ******
; -----> 8000 special <------
al w1 x2-a241 ;
; -----> end 8000 special <------
al w0 8.0377 ;
la w0 x1+a500 ; if main.gen_info.result = no_credit or
se w0 6 ; main.gen_info.result = illigal_link then
sn w0 7 ; panic; <* protocol error *>
jl -1 ;
rs. w0 i6. ; <* save result *>
;
rl w0 b227 ; if main.gen_info.answer then <* bit 1<16 *>
la w0 x1+a500 ; begin
sn w0 0 ;
jl. j1. ; main.free_buffers :=
al w0 1 ; main.free_buffers + 1;
ba w0 x1+a78+0 ;
hs w0 x1+a78+0 ; end;
j1: ;
rl w0 b219 ; <* middle octet *>
la w0 x1+a500 ;
ls w0 -8 ;
rl w3 x1+a503 ;
sn w3 0 ; if process-id = 0 then
jl. j2. ; skip errorlog check;
se w3 (b32) ; if special watched receiver or
se w0 0 ; check<>0 then
sz ;
jl. j2. ; begin
rx w1 6 ;
jl w2 (b31) ; < call error-log >
al w1 x3 ;
al w2 x1+a241 ;
; end;
j2: ;
rl w3 b218 ; <* left octet *>
la w3 x1+a500 ;
ls w3 -15 ;
sl w3 63 ; if main.function > 15 then
jl -1 ; panic;
;
rl. w0 i6. ; <* w0: result, w1: main, w2: main+a241 *>
jl. (x3+j3.) ; goto case function of
;func, a :
j3: -1 ; 0 0 : undef
-1 ; 0 1 : undef
-1 ; 1 0 : undef
c47 ; 1 1 : answer device operation
c48 ; 2 0 : create link - deliver interrupt
c48 ; 2 1 : answer create link - deliver interrupt
-1 ; 3 0 : undef
c48 ; 3 1 : answer remove link - deliver interrupt
c48 ; 4 0 : attention - deliver interrupt
-1 ; 4 1 : undef
-1 ; 5 0 : undef
c48 ; 5 1 : answer regret - deliver interrupt
-1 ; 6 0 : undef
c48 ; 6 1 : answer reserve device - deliver interrupt
-1 ; 7 0 : undef
c48 ; 7 1 : answer release device - deliver interrupt
c48 ; 8 0 : remove link request - deliver interrupt
-1 ; 8 1 : undef
-1 ; 9 0 : undef
c48 ; 9 1 : answer initialize controller - deliver interrupt
-1 ; 10 0 : undef
c47 ; 10 1 : answer supervisor_operation
-1 ; 11 0 : undef
c48 ; 11 1 : answer reset
-1 ; 12 0 : undef
c48 ; 12 1 : answer stop normal communication
-1 ; 13 0 : undef
c47 ; 13 1 : answer operator message
-1 ; 14 0 : undef
-1 ; 14 1 : answer close system: just panic
-1 ; 15 0 : undef
-1 ; 15 1 : answer reload system: just panic
i6: 0 ; save result
;
e. ; end;
; interrupt acknowledge procedure
;
; the controller has read it's communication area
;
; call
; w0 -
; w1 -
; w2 - (8000 special: main + a229)
; w3 -
;
b. j5 w.
c46: ; procedure acknowledge interrupt
; begin
c. l53 b. f4 w. ; ****** test 45 ******
rs. w3 f1. ;
al w1 x2-a229 ;
rs. w1 f0. ;
jl. w3 (f3.) ;
45 ;
f0: 0 ; main
f1: 0 ;
jl. f2. ;
al w0 x1+a551 ; dump message buffer address
al w1 x1+a551 ;
jl. w3 (f4.) ;
jl. f2. ;
f3: d150 ;
f4: d151 ;
f2: ;
e.z. ; ****** end test 45 ******
;
; ------> RC8000 special <-------
al w1 x2-a229 ;
; ------> end RC8000 special <-------
ac w0 2.010000+1;
la w0 x1+a78 ; main.com_state := ready;
hs w0 x1+a78+1 ;
;
c42: ; entry2: <* after answer device *>
rl w2 x1+a81 ; element := main.waiting_q.first;
sn w2 x1+a81 ; if element = none then
jl c99 ; return_from_interrupt;
al w0 0 ; force :=
sl w2 (b8+4) ;
sl w2 (b8+6) ; if element <> message then no
jl j2 ;
al w0 2.1000000 ; else message.state.force;
la w0 x2+a138 ;
ls w0 -6
j2: ;
jl. (+2) ; test_ready_and_setup(force, message);
d142 ;
; end;
e.
; procedure deliver clock interrupt.
; only the clock interrupt from the i-o mp (or the cpu) is transferred to
; the monitor clock driver.
; return: interrupt return
c49: al w0 0 ;
b. h0 w. ; if mp then
am (b9) ; get pu index
h0=k ;
jl. 0 ;
gg w0 b108 ;
c.(:h0+a8-k-1:)
am 0, r.(:h0+a8+2-k:)>1
z.
e. ; end
sn w2 (x2) ; if in queue or
se w0 0 ; not i-o pu or cpu then
jl c99 ; return
jl c50 ; else deliver interrupt
; procedure deliver external interrupt
;
; when an external interrupt is accepted by the monitor,
; control is transferred out into the corresponding
; device description, which should contain:
;
; dev descr + a240 : jl w2 c51
;
; return must be made to the standard interrupt return action,
; which will take care of a possible selection of the driver.
;
; call: w2 = dev descr + a241
; return address = interrupt return
c51: rl w3 x2-a241+a230; w3 := top of executed channel program;
al w0 4 ; result := 4; (i.e. prepare for abnormal termination)
se w3 0 ; if top command address defined then
bl w3 x3-6+1 ; w3 := last command executed;
sn w3 -1<8 ; if last command = 'stop' then
al w0 0 ; result := 0;
sn w3 4<8 ; if last command = 'wait' then
al w0 5 ; result := 5;
c50: al w3 c99 ; link := interrupt return;
; continue with deliver interrupt
; procedure deliver interrupt
; function: delivers the interrupt operation in the event queue
; of the corresponding driver process.
; the driver process is started, if it was waiting for
; an event.
;
; call: w0 = result (=0, 1, 2, 3, 4, 5, 6), w2 = operation, w3 = link
; exit: all regs undef
; return address: link
b. h10 w. ;
d121:rs w3 h0 ; save (return);
jl w1 d131 ; set result and descrease all stopcounts;
; w2 = device descr
rl w1 x2+a250 ; driver := driverproc (device descr);
sh w1 0 ; if driver undefined then
jl -10 ; test test
; jl (h0) ; return;
al w2 x2+a241 ; oper := timeout operation (device descr);
rl w3 h0 ; restore (return);
bz w0 x1+a13 ; state := state(driver);
sn w0 a104 ; if driver is waiting for event then
jl d127 ; goto take interrupt;
al w1 x1+a15 ; link (event queue (driver) , oper);
rl w3 x1+2 ;
rs w2 x1+2 ;
rs w2 x3+0 ;
rs w1 x2+0 ;
rs w3 x2+2 ;
jl (h0) ;
h0: 0 ; saved return;
e. ;
; procedure take interrupt
; function: let the driver receive the interrupt operation at once
;
; call: w1 = driver process, w2 = interrupt operation, w3 = link
; exit: all regs undef
; return address: link
d127:al w2 x2-a241+a246;
rs w2 x1+a30 ; save w2 (driver) := address of driver service inst
al w0 2 ; save w0 (driver) := 2; i.e. indicate interrupt;
rs w0 x1+a28 ; link internal (driver);
zl w0 x1+a13 ; if process not running then
se w0 a94 ; link process to running queue
jl d10 ;
jl x3 ;
; procedure prepare driver(proc)
; function: initializes current external process and current buffer
; exits to the interrupt address given in proc:
; int addr : normal exit
;
; the call must be made like this:
;
; proc + a246: jl w1 c30 ; driver service instruction
; ---
; proc + a245: interrupt address
; ---
; proc + a54 : next message buf
;
; call: w1 = proc + a247
; exit: w0 = result(proc), w1 = proc, w2 = buf(proc)
; int.addr : normal exit
c30: al w1 x1-a247 ;
rs w1 b19 ; current receiver := buf;
rl w2 x1+a54 ;
rs w2 b18 ; current buffer address := next mess(proc);
rl w0 x1+a244 ; result := timeout(proc);
jl (x1+a245) ; goto interrupt address(proc);
; procedure clear device
;
; function: everything is cleared-up in the device description,
; i.e. the controller is reset (except after 'wait'-program)
; a possible pending interrupt is cleared
; a possible pending interrupt operation is removed
; if any stopcounts were increased, they will be decreased
;
; call: w1 = link, w2 = device descr
; exit: w2 = unchanged, w0, w1, w3 = undef
; return address: link
b. i5, j5 w.
i1: 0 ; saved return
;
d129: ; unconditionally reset:
am a235-a225; <point at something <> 0>
d130: ; conditionally reset:
rl w0 x2+a225 ; note: the controller is not reset when a
rl w3 x2+a235 ; wait program is timed out;
sn w0 0 ; if transfer in progress then
jl j1 ; begin
rs w1 i1 ; <w3: physical device address>
al w1 3 ; if proc.kind = ifpmain then
rl w0 x2+a10 ; reset device(ifp-reset)
sn w0 q26 ; device address := physical address;
rs w3 b58 ;
se w0 q26 ; else
am 2.01<1 ; reset device(normal reset);
do w1 x3+0 ; note: ifp: sub address must be zero - reset is
rl w1 i1 ; signaled in work register!
j1: ; end;
ls w3 1 ; entry := device address
ls w3 -1 ; (remove bit 0)
wa w3 b65 ; + controller table base;
rl w0 x3+a313 ; w0 := interrupt number(controller table (entry));
gp w0 b95 ; clear interrupt bit in cpu;
al w2 x2+a242 ; oper := timeout operation(device descr);
; continue with set result and decrease all stopcounts
; (result = undef)
e.
; procedure set result and decrease all stopcounts
;
; call: w0 = result: 0 = transfer terminated by stop
; 1 = bus reject when started
; 2 = bus timeout when started (i.e. disconnected)
; (3 = software timeout)
; 4 = transfer terminated, before stop
; 5 = wait-program terminated
; (6 = power restart)
; w1 = link w2 = timeout operation
; exit: w2 = device description, w0, w1, w3 = undef
d131:rs w0 x2-a241+a244; save result in timeout-field;
se w2 (x2) ; (if in timer queue then
jl w3 d5 ; remove(timeout operation); )
al w2 x2-a241 ; w2 := device descr;
; continue with decrease all stopcounts
; procedure decrease all stopcounts
;
; function: if any stopcounts increased, then decrease them again
; transfer code(device descr) := 0
;
; call: w1 = link, w2 = device descr
b. h10, i10 w. ;
ds w2 h1 ; save (link, device descr);
rl w1 x2+a225 ; get transfer code(device descr);
sn w1 -1 ; if no transfer to processes then
jl i1 ; goto clear up;
so w1 2.1 ; if transfer code odd then
jl i0 ; begin i.e. transfer to/from driver area;
rl w1 x2+a250 ; driver := driver process (device descr);
jl w3 d133 ; decrease stopcount(driver);
rl w2 h1 ; restore(device descr);
al w1 -1<1 ;
la w1 x2+a225 ; restore (transfer code) (even)
i0: ; end;
sn w1 0 ; if transfer code shows transfer to/from sender the
jl i1 ; begin
jl w3 d133 ; decrease stopcount(sender);
rl w2 h1 ; restore (device descr);
; end;
i1: al w1 0 ; clear up:
rs w1 x2+a225 ; transfer code(device descr) := 0; i.e. no transfer
jl (h0) ; return;
h0: 0 ; saved return
h1: 0 ; saved device descr
e. ;
; procedure decrease stopcount(sender.mess): d132
; procedure decrease stopcount(process): d133
;
; function: the stopcount of the process is decreased by 1.
; if the stopcount becomes zero, and the process is waiting
; to be stopped, the process is stopped now (i.e. put in
; the state 'waiting for start by...'), and the following will
; be done:
; if the process was stopped by its parent, the stop-answer
; will be send to the parent (as defined by the wait-address
; in the process), indicating that the stopping has been
; accomplished.
; the decrease-action is repeated for the parent etc.etc.
;
; call: d132: w2= message or
d132:
rl w1 x2+a142 ; proc= sender(mess)
sh w1 0 ; if regretted then
ac w1 x1 ; proc= -sender(mess)
rl w0 x1+a10 ; if kind.proc = pseudo then
sn w0 64 ; proc = main proc.sender
rl w1 x1+a50 ;
sz w0 -1-64 ; if proc is neither internal nor pseudo then
rl w1 b21 ; proc = driverproc (there is only one)
; (continue with d133)
; call: d133: w1 = process, w3 = link
; exit: all regs undef
; return address: link
b. i10 w. ;
d133:rs w3 i3 ; decrease stopcount:
i0: al w0 -1 ; loop:
ba w0 x1+a12 ; stopcount (process) :=
hs w0 x1+a12 ; stopcount (process) - 1;
bz w2 x1+a13 ;
sn w0 0 ; if stopcount <> 0 or
so w2 a105 ; process not waiting for being stopped then
jl (i3) ; return;
al w0 x2+a106 ; state (process) := state (process)
hs w0 x1+a13 ; + 'waiting for start';
; prepare for repeating the loop:
rl w2 x1+a40 ; buf := wait address(process);
rl w1 x1+a34 ; process := parent (process);
se w0 a99 ; if state <> 'waiting for start by parent' then
jl i0 ; goto loop;
; prepare the buffer for returning the answer:
al w0 1 ; receiver(buf) := result := 1;
jl. w3 (i1.) ; deliver answer(buf);
jl i0 ; goto loop;
i1: d15 ;
i3: 0 ; saved return;
e. ;
; procedure activate_process(internal)
;
; sw-implementation of 'ap'-instruction.
; when using this procedure it is possible to connect and disconnect
; cpu's during normal operation only by increase and decrease b82.
;
; call return
; w0 - destroyed
; w1 internal internal
; w2 - destroyed
; w3 link destroyed
;
; return: link + 0: no free pu
; link + 2: internal has been activated
;
b. i5, j5 w.
d4: ; procedure activate_process(internal)
rl w2 (b59) ; begin
rl w0 x2+0 ;
sh w0 0 ; if pu_table.free_pu = 0 then
jl x3+0 ; return(link);
;
rs. w3 i3. ;
rl w3 x1+a186 ;
am x3 ;
rl w0 x2+2 ;
ls w3 -1 ; if internal.last_pu < no_of_pu and
sl w3 (b82) ; pu_table(internal.last_pu) = 0 then
jl. j1. ; begin
ls w3 +1 ;
sn w0 0 ; selected_pu := internal.last_pu;
jl. j3. ; end
j1: ; else
rl w3 b82 ; begin
ls w3 +1 ; selected_pu := no_of_pu;
j2: am x3 ; while pu_table(selected_pu) <> 0 do
rl w0 x2 ; begin
al w3 x3-2 ; selected_pu := selected_pu - 1;
se w0 0 ;
jl. j2. ; end;
j3: ; end;
al w0 -1 ;
wa w0 x2+0 ; pu_table.free_pu :=
rs w0 x2+0 ; pu_table.free_pu - 1;
am x3 ;
rs w1 x2+2 ; pu_table(selected_pu) := internal;
rl. w3 i3. ;
jl x3+2 ; return(link+2);
;
i3: 0 ; saved link
e. ; end;
; elementary link-procedures:
; procedure remove(elem);
; comment: removes a given element from its queue and leaves the element linked to itself.
; call: w2=elem, w3=link
; exit: w0, w1, w2=unchanged, w3=next(elem)
; return address: link
b. i1 w.
d5: rs w3 i0 ; save return;
rl w3 x2 ; w3 := next(elem);
rx w2 x2+2 ; w2 := prev(elem); prev(elem) := elem;
rs w3 x2 ; next(w2) := next(elem);
rx w2 x3+2 ; w2 := elem; prev(next(elem)) := old prev(elem);
rs w2 x2 ; next(elem) := elem;
jl (i0) ; return;
; procedure increase bufclaim, remove release buf;
; comment: bufclaim(cur) is increased, continue with release buf
; call: w1=cur, w2=buf, w3=link
; exit: w0, w1=undef, w2, w3=unchanged
; return address: link
d109: ;
al w0 1 ;
ba w0 x1+a19 ; increase(bufclaim(cur));
hs w0 x1+a19 ;
; continue with d106
; procedure remove release buf;
; comment: removes the buffer from its queue, continue with release mess buf
; call: w2=buf, w3=link
; exit: w0, w2, w3=unchanged, w1=undef
; return address: link
d106: ;
al w1 x3 ; save return
jl w3 d5 ; remove (buf);
al w3 x1 ; restore return;
; continue with d13
; procedure release mess buf(buf);
; comment: clears sender and receiver and links the buffer to the pool.
; call: w2=buf, w3=link
; exit: w0=unchanged, w1=undef, w2, w3=unchanged
; return address: link
d13: al w1 0 ; sender(buf):=0;
rs w1 x2+4 ; receiver(buf):=0;
rs w1 x2+6 ;
al w1 b8 ; head := mess buf pool head; (i.e. link in rear);
; procedure link(head, elem);
; comment: links the element to the end of the queue
; call: w1=head, w2=elem, w3=link
; exit: w0, w1, w2=unchanged, w3=old last(head);
d6: rs w3 i0 ; save return;
rl w3 x1+2 ; old last:=last(head);
rs w2 x1+2 ; last(head):=elem;
rs w2 x3+0 ; next(old last):=elem;
rs w1 x2+0 ; next(elem):=head;
rs w3 x2+2 ; last(elem):=old last;
jl (i0) ; return;
i0: 0 ; saved return: remove, link
e.
; ****** stepping stones for absolute addresseable monitor routines ******
;
; procedure claim buffer(cur, buffer); <* d108 *>
;
; call return
; w0 - destroyed
; w1 cur cur
; w2 buffer buffer
; w3 link link
;
d108: jl. (+2) ; claim buffer
d58 ;
; procedure regretted message(buffer); <* d75 *>
;
; call return
;
; w0 - unchanged
; w1 - unchanged
; w2 buffer buffer
; w3 link destroyed
;
d75: jl. (+2) ; regretted message
d65 ;
; procedure check mess area and name (save w3) area;
; procedure check name (save w3) area;
; procedure check name (save w2) area;
; comment: checks that the areas are within the process
;
; call: w1=cur, w3=link
; exit: w0=undef, w1=unchanged, w2=name, w3=unchanged
; return addr: link: within process
; c29 : not within process
d110: jl. (+2) ; check message area and name area:
d66 ;
d17: jl. (+2) ; check name (save w3) area:
d67 ;
d111: jl. (+2) ; check name (save w2) area:
d115 ;
; procedure check within(first, last);
; comment: checks that the specified area is within the process
; call return
; w0 last last
; w1 cur cur
; w2 first first
; w3 link link
; return: link: within process
; c29 : not within process
d112: jl. (+2) ; check within:
d116 ;
; procedure check message area and buf
; call return
; w0 - destroyed
; w1 cur cur
; w2 - buf
; w3 link link
; return: link: ok
; c29 : mess area outside cur
; c29 : buf not message buf
d103: jl. (+2) ; check message area and buf
d117 ;
; procedure check message buffer;
; checks whether the save w2 of the internal process is a message buffer address
; call return
; w0 - destroyed
; w1 cur cur
; w2 - buf
; w3 link link
d12: jl. (+2) ; check message buffer:
d68 ;
; procedure check event(proc, buf);
; checks that buf is the address of an operation in the event queue of
; the internal process
; call return
; w0 - destroyed
; w1 proc proc
; w2 buf buf
; w3 link link
; return: link: buffer address ok
; c29: buf is not in the queue
d19: jl. (+2) ; check event:
d69 ;
; procedure conditional reschedule
; procedure unconditional reschedule
; If the 'conditional' entrypoint is used, the internal process is
; rescheduled if 'no of free pu' in the pu-table is 0 otherwise no
; rescheduling is performed. This test is done because there is no
; need for rescheduling if ther is an idle pu; if done the process
; may change pu and the cache will be destroyed.
; call return
; w0 - destroyed
; w1 internal internal
; w2 - destroyed
; w3 link destroyed
;
d20: jl. (+2) ; conditional reschedule
d40 ;
d21: jl. (+2) ; unconditional reschedule
d41 ;
; procedure check and search name (=d17+d11);
;
; call: w1=cur, save w3(cur)=name, w3=link
; exit: w0, w1=unchanged, w2=name, w3=entry
; return address: link: entry not found
; link+2: entry found
; c29 : name area outside current process
d101:jl. (+2) ; check and search name;
d43 ;
; the following procedures searches the name table for a given entry and delivers its entry in
; the name table. if name is undefined, the entry is name table end.
; procedure search name(name, entry);
; call: w2=name, w3=link
; exit: w0, w1, w2=unchanged, w3=entry
; return address: link : name not found, w3=(b7)
; link+2: name found
d11: jl. (+2) ; search name;
d44 ;
; procedure search name(name, entry, base);
; call: w0, w1=base, w2=name, w3=link
; exit: w0, w1=undef, w2=unchanged, w3=entry
; return address: link : name not found, w3=(b7)
; link : name found, w3 <> (b7)
d71: jl. (+2) ; search name;
d45 ;
a107 ; max base lower
d72: a108 ; max base upper
a107-1 ; extreme lower
d73: a108+1 ; extreme upper
; procedure update time(slice);
; comment: senses the timer and updates current time slice and time;
;
; call: w3=link
; exit: w0=undef, w1=unchanged, w2=new clock, w3=unchanged
; return address: link
b. i9, j4 w.
d7: gg w2 b94 ;
al w0 0 ;
b. h1 w. ; if mp then
am (b9) ;
h0=k
jl. 0 ; begin
gg w0 b108 ; get pu index
c.(:h0+a8-k-1:)
am 0, r.(: h0+a8+2-k :)>1 ; fill up
z.
e. ; end mp
sn w0 0 ; if not i-o pu or cpu then
jl. i6. ; begin
rl. w0 i9. ; rct(i-o mp) := undefined
rs w0 (b38) ; get clock from i-0 mp
al w0 a194 ; wait until rct(i-o mp) defined
do w0 (b74) ;
j4: rl w2 (b38) ;
sn. w2 (i9.) ;
jl. j4. ; end
i6:
al w0 x2 ; new value:=sense(timer);
ws w2 b14 ; increase:=new value-clock;
rs w0 b14 ; clock:=new value;
sh w2 -1 ; if increase<0 then
wa w2 i9 ; increase:=increase+size of clock;
; comment: timer overflowed...;
rx w0 4 ;
wa w0 b13+2 ;
rs w0 b13+2 ; time low:=time low+increase;
sx 2.01 ;
jl i8 ; if carry then
jl x3 ;
i8: al w0 1 ; time high:=time high+1;
wa w0 b13 ;
rs w0 b13 ;
jl x3 ; return;
i9: 1<16 ; increase when timer overflows;
;procedure activate process
;comment: unlinks the first proc in running queue, increases stopcount
; and sets the state to running,
; call: return:
; w0: undefined
; w1: proc
; w2: proc+a16 (running queue link)
; w3: link undefined
d8: rs w3 j0 ; save return;
rl w2 b2 ; get first in running queue
al w1 x2-a16 ; w1:= proc
al w0 1 ; proc.stopcount:=
ba w0 x1+a12 ; proc.stopcount + 1
hs w0 x1+a12 ;
al w0 a94 ; proc.state:= running
hs w0 x1+a13 ;
jl w3 d7 ; update time;
al w0 x2 ;
al w2 x1+a16 ;
ws w0 x1+a35 ; proc.quantum := starttime
rs w0 x1+a35 ;
rl w3 x2 ; unlink proc
rx w2 x2+2 ;
rs w3 x2 ;
rx w2 x3+2 ;
rs w2 x2 ;
jl (j0) ; return
; the following entries removes the current process from the timequeue, and initializes state.
; call: w1=cur
; return address: interrupt return
d105: ; remove wait message:
; bz w0 x1+a19 ;
; sn w0 0 ; if buf claim(cur)=0 then
; jl d108 ; goto claim buffer (and exit with save w2=0);
am a102-a104 ; state:=wait message;
d107: ; remove wait event:
am a104-a103 ; state:=wait event;
d104: ; remove wait answer:
al w0 a103 ; state:=wait answer;
al w3 c99 ; return:=interrupt return;
; continue with remove internal;
; procedure passivate process (new state)
; passivates the current process i.e
; - decreases stopcount (eventually stopping the process)
; - updates the time quantum used by the process
; - sets the state to new state if the process has not been stopped
;
; call return
;w0 new state process state
;w1 proc undefined
;w2 proc.timeq (proc +a16)
;w3 link undefined
d9:
ds w0 j1 ; save state , return, and proc
rs w1 j2 ;
jl w3 d7 ; update time
sh w2 (x1+a35) ; if stoptime > starttime then
wa. w2 i9. ; stoptime := stoptime + size of clock
ws w2 x1+a35 ; proc.quantum:= stoptime-starttime
rs w2 x1+a35 ;
dl w3 b13+2 ; proc.start wait:= now
ds w3 x1+a39+2 ;
jl w3 d133 ; test and decrease stopcount
al w0 0 ; rescedule count := 0
al w1 0 ;
b. h1 w. ;
am (b9) ;
h0=k ;
jl. 0 ;
gg w1 b108 ;
c. (:h0+a8-k-1:) ;
am 0, r.(:h0+a8+2-k:)>1;
z. ;
e. ;
rs w0 x1+b83 ;
rl w1 j2 ; if proc.state still is running then
zl w0 x1+a13 ;
sn w0 a94 ;
rl w0 j1 ; proc.state:= new state
hs w0 x1+a13 ;
al w2 x1+a16 ;
b. h1 w. ; if mp then
am (b9) ;
h0=k
jl. 0 ; begin
dp ; deactivate process;
c.(:h0+a8-k-1:)
am 0, r.(: h0+a8+2-k :)>1 ; fill up
z.
e. ; end mp
jl (j0) ;
j0: 0 ; return
j1: 0 ; new state
j2: 0 ; current process
; return;
i0: 0 ; saved return
; procedure link internal(proc);
; comment: links the internal process to the timer queue. the timer queue is kept as a
; sorted list, according to the priority. (the smaller the priority is, the better
; is the priority).
; if the time quantum is less than the maximum time slice, the process will be
; linked up in front of other processes with the same priority. otherwise in the
; rear (the time quamtum of the process is transferred to runtime(proc), except
; the amount which is already used of the next quantum).
; call: w1=proc, w3=link
; exit: w0, w1, w2, w3=undef
d10: rs w3 i0 ; save(return);
al w0 a95 ;
hs w0 x1+a13 ; state(proc):=waiting for cpu;
al w2 x1+a16 ;
rl w3 x1+a301 ; priority:=priority(proc);
rl w1 x1+a35 ;
sl w1 (b10) ; if quantum(proc)>=max slice then
jl i3 ; goto insert in rear;
al w3 x3-1 ; (code facility);
al w1 b2 ; worse:=timer q head;
i1: rl w1 x1 ; next: worse:=next(worse);
sn w1 b2 ; until last
jl i2 ;
sl w3 (x1-a16+a301) ; if priority(worse)<priority then
jl i1 ; goto next;
i2: ; insert process:
rl w3 x1+2 ;
rs w2 x1+2 ;
rs w2 x3+0 ;
rs w1 x2+0 ;
rs w3 x2+2 ;
jl (i0) ; internal then return;
; the process has been in front of the queue for more than the max time slice.
; the run time should be updated with all the quantum, but this would give the process a
; complete time slice next time. instead the used quantum is split in two parts:
; the amount by which it exceeds a multiplum of the max slice, and the rest. these parts
; are the increase in runtime and the new quantum.
; finally the process is inserted in the rear of the timer queue, according to priority.
i3: al w0 a85-1 ; w0 := mask for extracting new quantum;
la w0 2 ; quantum(proc) := quantum(proc) extract slice;
rs w0 x2-a16+a35;
ws w1 0 ;
al w0 0 ;
aa w1 x2-a16+a36+2; add the remaining part of quantum to
ds w1 x2-a16+a36+2; runtime(proc);
al w1 b2 ; insert process in rear of queue
al w3 x3+1 ; (code facility)
i4: rl w1 x1+2 ; next: worse:=last(worse);
sn w1 b2 ; if worse<>timer q head and
jl i5 ;
sh w3 (x1-a16+a301) ; priority(worse)>priority then
jl i4 ; goto next;
; notice: the loop went one step to far . . .;
i5: rl w1 x1 ; now w1 has been repaired;
jl i2 ; goto insert proc;
e.
\f
m. end of link internal
; to facilitate the error recovery the interrupt stack and the
; stationary pointers of the monitor table are placed at fixed
; addresses.
b128=1200, 0,r.(:b128-k+2:)>1-7
a125 ; job host identification
a130 ; date of options
a131 ; time of options
t.
m. copies of some mon table entries, int stack, mon reg dump (26, 32, 26 hw)
; copy of some monitor pointers:
0-0-0 ; b3: 72: name table start
0-0-0 ; b4: 74: first device in name table
0-0-0 ; b5: 76: first area in name table
0-0-0 ; b6: 78: first internal in name table
0-0-0 ; b7: 80: name table end
0-0-0 ; b8+4: 86: first byte of mess buf pool area
0-0-0 ; b8+6: 88: last byte of mess buf pool area
0-0-0 ; b22: 92: first drum chain in name table
0-0-0 ; b23: 94: first disc chain in name table
0-0-0 ; b24: 96: chain end in name table
b50 ; start of interrupt stack
0-0-0 ; b86: driver proc save area
a135<12+a136 ; 64: release, version of monitor
0-0-0 ; b59: 56: pu inf table
0-0-0 ; b79: 124: interrupt stat table
0-0-0 ; b81: 126: monitor call stat table
0-0-0 ; reserved
0-0-0 ; reserved
0-0-0 ; reserved
; definition of interrupt stack:
b50: 0 ; end of stack
b49=k-1 ; terminating stack-address
; power fail element:
0 ; (irrellevant regdump)
0 ; (exception disabled)
-1 ; (escape disabled)
0 ; (monitor call not permitted in monitor)
c8 ; external interrupt, second level
1 < 23 + 0 ; monitor mode + totally disabled
; monitor element:
b52 ; monitor regdump
0 ; monitor exception routine
b51: -1 ; current process in monitor (escape not used in monitor mode
c0 ; monitor call entry
c1 ; external interrupt entry, first level
1 < 23 + 6 ; monitor mode + disable all but power/bus error
; user element:
0-0-0 ; user regdump (initialized by select internal)
0-0-0 ; user exception ( - - - - )
0-0-0 ; user escape ( - - - - )
; monitor regdump area
;
; used when initializing the whole system,
; and to hold the working registers etc. in case of
; powerfailure or buserror during monitor code
b52: 0 ; w0 = 0 (irrellevant)
0 ; w1 = 0 (irrellevant)
0 ; w2 = 0 (irrellevant)
0 ; w3 = 0 (irrellevant)
1 < 23+1<5 ; status = monitor mode + no process active
c99 ; ic = interrupt return
0 ; cause = 0 (irrellvant)
0 ; sb = 0 (irrellvant)
0 ; cpa = 0 (irrellevant)
0 ; base = 0 (irrellevant)
8 ; lower write limit
8.3777 7777 ; upper write limit = all possible core
0 < 12 + 6 ; interrupt limits
0 ; puindex
; procedure move message(from, to); <* d14 *>
;
; call return
; w0 - destroyed
; w1 from from
; w2 to to
; w3 link destroyed
;
d14: jl. (+2) ; move message
d64 ;
; return result in save w0(cur);
; entry: w1=cur
r5: am 5-4 ;
r4: am 4-3 ;
r3: am 3-2 ;
r2: am 2-1 ;
r1: am 1-0 ;
r0: al w0 0 ;
r28: rs w0 x1+a28 ; save w0:=result;
jl c99 ; goto interrupt return;
; procedure remove user(internal, proc); <* d123 *>
; procedure remove reserver(internal, proc); <* d124 *>
;
; call return
; w0 - destroyed
; w1 internal internal
; w2 proc proc
; w3 link link
;
d123: jl. (+2) ; remove user
d53 ;
;
d124: jl. (+2) ; remove reserver
d54 ;
; procedure insert reserver(internal, proc); <* d125 *>
; procedure insert user(internal, proc); <* d126 *>
;
; call return
; w0 - destroyed
; w1 internal internal
; w2 proc proc
; w3 link link
;
d125: jl. (+2) ; insert reserver
d55 ;
;
d126: jl. (+2) ; insert user
d56 ;
; procedure lock monitor
; returns disabled!
b. h0 w.
d80: ;
am (b9) ; if mp then
h0=k ;
je. 0 ; (lock must be called with interrupts enabled)
lk b51 ; lock(monitor);
c.(:h0+a8-k-1:)
am 0 ;
r.(:h0+a8+2-k:)>1 ;
z.
jd x3 ; return disabled
; procedure unlock
; returns enabled
d81: ;
am (b9) ; if mp then
h0=k ;
jl. 0 ;
ul b51 ; unlock(monitor)
c.(:h0+a8-k-1:)
am 0
r.(:h0+a8+2-k:)>1
z.
je x3 ; returns enabled
e.
\f
; comment: the following utility procedures are used by external
; processes during input/output;
; procedure deliver result(result)
; comment: moves the general input/output answer to the beginning of the driver process.
; (the last 3 words of the message buffer are copied too, so they will remain unchanged).
; the answer is send with the specified result to the sender of the buffer.
;
; call: w0 = result, w3 = link, b18 = buffer
; exit: w0 = undef, w1 = proc (= b19), w2 = undef, w3= unchanged
; return address: link: answer delivered
; (internal 3 if buf not claimed and claims exceeded)
b. i10 w.
g3: am 5-4 ; result 5:
g4: am 4-3 ; result 4:
g5: am 3-2 ; result 3:
g6: am 2-1 ; result 2:
g7: al w0 1 ; result 1: w0 := result;
rl w3 b20 ; return := wait-next action in driver process;
jl g19 ; goto deliver result;
g18: al w0 1 ; result 1: w0 := result;
g19: ; deliver result:
jd k+2 ; disable;
ds w0 i3 ; save(link, result);
rl w1 b21 ; cur = driverproc
rl w2 b18 ; buf := current buffer;
ac w3 (x2+4) ;
sl w3 0 ; if receiver(buf) > 0 then
jl i0 ; begin comment: buf not claimed, see link operation;
bz w0 x1+a19 ; if bufclaim(cur) <> 0 then
sn w0 0 ; begin
jl i0 ; decrease(bufclaim(cur));
bs. w0 1 ; receiver(buf) := -receiver(buf);
hs w0 x1+a19 ; end; (i.e. claims exceeded will provoke a break below);
rs w3 x2+4 ; end;
i0: rl w0 x1+a182 ;
rl w1 x1+a302 ;
wa w1 0 ; get physical address of save area
dl w0 x2+a151 ; save first four words of mess.
ds w0 g29 ; (used by errorlog )
dl w0 x2+a153 ;
ds w0 g30 ;
dl w0 x2+22 ; move last 3 words from buf
ds w0 x1+14 ; to area;
rl w0 x2+18 ; (to retain compatibility with old conventions)
rl w3 g24 ;
ds w0 x1+10 ; move the 5 std answer words
dl w0 g23 ; to area;
ds w0 x1+6 ;
dl w0 g21 ;
ds w0 x1+2 ; (you are disabled, so do not worry about timeslicing...);
dl w0 i3 ; restore (link, result);
am (b21) ;
rl w1 +a302 ; get logical address of save area
jd 1<11+22; send answer(result, area, buf);
rl w1 b19 ; w1 := current receiver;
rl w2 x1 ; if kind of receiver=subprocess then
se w2 84 ; check status
sn w2 85 ; else return
jl. i1. ;
jd x3 ;
i1: rl w2 g20 ; if one or more of statusbits 1,2,4,9,10,11
se. w1 (b32.) ; or if receiver = special watched receiver
sz. w2 (i5.) ; then
jl w2 (b31) ; call errorlog
jd x3 ; restore link and return
i2: 0 ; saved link
i3: 0 ; saved result
b32: -2 ; proc adr for special watched receiver
m. statusmask for errorlog
i5: 8.36070000 ; status mask: bit 1 2 3 4 9 10 11
; procedure link operation (buf)
; comment: links a message to the receiver and returns to the receiver, in case it is the only
; message in the queue (and interrupt address is even).
; otherwise it returns to the wait-next action in the driver process.
;
; call: w2 = buf, w3 = link
; exit: w0 = operation, w1 = proc, w2 = unchanged, w3 = unchanged
; return address: link: single in queue
; (b20): others in queue
; (b20): interrupt addr odd (i.e. driver busy)
g17: jd k+2 ; link operation:
rs w3 i3 ; save return;
ac w3 (x2+4) ;
sh w3 0 ; if receiver(buf) < 0 then
jl i4 ; begin comment: buf claimed. now release claim;
rs w3 x2+4 ; receiver(buf) := -receiver(buf); i.e. positive;
rl w1 b21 ; cur = driverproc
bz w3 x1+a19 ; increase(buf claim(cur));
al w3 x3+1 ;
hs w3 x1+a19 ; end;
i4: am (b19) ;
al w1 +a54 ;
jl w3 d6 ; link(mess q(proc), buf);
se w3 x1 ; if old last <> mess q(proc) then
c33: jl (b20) ; goto wait next(driver process);
al w1 x1-a54 ; w1 := proc;
rl w0 x1+a56 ; w0 := interrupt addr(proc);
so w0 2.1 ; if interrupt addr(proc) is odd then
jl w3 g64 ;+2 goto wait next(driver process);
jl (b20) ;+2 examine queue: empty => goto wait next;
jl (i3) ; return
e.
; procedure check user
; comment: checks whether an external process is used
; by the current internal process. if the external is reserved
; it is also checked whether it is reserved by the current
; internal process.
; call: return:
; w0 destroyed
; w1 cur cur
; w2 buf buf
; w3 link destroyed
b. i5 w.
g14: ; check user;
sn w1 (b 21) ; if curr.intproc=driverproc then
jl x3 ; return
ds w3 i3 ; save w2 w3;
rl w2 b19 ; w2:= extproc;
jl w3 d113 ; check reserver;
jl g6 ; return 0 other reservers goto result 2 else
jl i0 ; return 2 intproc is reserver goto nornal return else
; return 4 no reservers
jl w3 d102 ; check user
jl g6 ; if not user then result 2 else
i0:
rl w2 i2 ;
jl (i3) ; normal return;
i2: 0 ; save w2;
i3: 0 ; save w3;
e. ; end
; procedure check reservation
; comment: checks whether an external process is reserved
; by the current internal process.
; call: return:
; w0 reserved
; w1 cur cur
; w2 buf buf
; w3 link link
b.i24 ; begin
w.
g15: ; check reserver;
sn w1 (b 21) ; if curr.intproc= driverproc then
jl x3 ; return ;
am (b19) ;
rl w0 a52 ; w0:=reserver.extproc;
sn w0 (x1+a14) ; if intproc is reserver then
jl x3 ; normal return else
jl g6 ; result 2;
e. ; end
; procedure check operation(oper mask, mode mask)
; comment: checks whether the operation and mode are
; within the repertoire of the receiver. the legal values are
; defined by two bitpatterns in which bit i=1 indicates
; that operation (or mode) number i is allowed. if the
; operation is odd, it is checked whether the input/output
; area is within the internal process.
; call: return:
; w0 oper mask destroyed
; w1 mode mask destroyed
; w2 buf buf
; w3 link destroyed
b.i24 ; begin
w.g16:rs w3 i0 ;
bz w3 x2+9 ;
ls w1 x3+0 ;
bz w3 x2+8 ;
ls w0 x3+0 ;
sh w0 -1 ; if mode mask(mode(buf))=0
sl w1 0 ; or oper mask (operation(buf))=0
jl g5 ; then goto result 3;
so w3 1 ;
jl (i0) ;
rl w1 x2+6 ;
dl w0 x2+12 ; if odd(operation(buf))
la w3 g50 ; make first and
la w0 g50 ; last address in buf even;
sl w3 (x1+a17) ; and (first addr(buf)<first addr(sender)
sl w0 (x1+a18) ; or last addr(buf)>=top addr(sender)
jl g5 ;
sh w0 x3-2 ; or first addr(buf)>last addr(buf))
jl g5 ; then goto result 3;
ds w0 x2+12 ; message even;
jl (i0) ;
i0: 0 ;
e. ; end
; input/output answer:
w.g20: 0 ; status
g21: 0 ; bytes
g22: 0 ; characters
g23: 0 ; file count
g24: 0 ; block count
g40: 0 ; word5
g41: 0 ; word6
g42: 0 ; word7
0 ; mess(1) operation
g29: 0 ; mess(2) first
0 ; mess(3) last
g30: 0 ; mess(4) segment no
; procedure next operation
; comment: examines the message queue of the receiver and
; returns to the receiver if there is a message from a
; not-stopped sender. otherwise it returns to the current
; internal process.
; call: return:
; w0 oper
; w1 proc
; w2 buf
; w3 link sender
b.i24 ; begin
w.g25:rs w3 i2 ;
jl w3 g64 ; examine queue(
jl c33 ; dummy interrupt);
jl (i2) ;
i2: 0 ;
e. ; end
; procedure examine queue(queue empty)
; call: return:
; w0 operation
; w1 proc
; w2 buf
; w3 link sender
b.i24 ; begin
w.g64:rs w3 i2 ;
i0: rl w1 b19 ; exam q:proc:=current receiver;
rl w2 x1+a54 ; buf:=next(mess q(proc));
sn w2 x1+a54 ; if buf=mess q(proc)
jl (i2) ; then goto queue empty;
rs w2 b18 ;
rl w3 x2+6 ; internal:=sender(buf);
xl x2+8 ;
sh w3 -1 ;
ac w3 x3+0 ;
bz w0 x3+a13 ;
rl w3 x2+6 ; if state(internal)=stopped
sx 2.1 ; and operation(buf)(23)=1
so w0 a105 ; or internal<0
sh w3 -1 ; then
jl i1 ; begin
bz w0 x2+8 ;
am (i2) ; no operation;
jl 2 ; goto exam q;
i1: jl w3 g26 ; end;
jl i0 ; oper:=byte(buf+8);
i2: 0 ;
e. ; end
; procedure no operation
; call: return:
; w0 destroyed
; w1 proc
; w2 destroyed
; w3 link destroyed
b.i24 ; begin
w.g26:al w0 1 ;
g27:al w1 0 ;
rs w1 g20 ; status:=
g28:rs w1 g21 ; bytes:=
rs w1 g22 ; character:=0;
jl g19 ; deliver result(1);
e. ; end
; procedure increase stop count
; comment: increases the stop count of the sender by 1.
; call: return:
; w0 unchanged
; w1 unchanged
; w2 buf buf
; w3 link destroyed
b.i24 ; begin
w.g31:rs w3 i0 ;
am (x2+6) ;
bz w3 a12 ;
al w3 x3+1 ; stop count(sender(buf)):=
am (x2+6) ; stop count(sender(buf))+1;
hs w3 a12 ;
jl (i0) ;
i0: 0 ;
e. ; end
; procedure decrease stop count
; comment: the stop count of the sender is decreased by 1
; if the operation is odd. if stop count becomes zero and the
; sender is waiting to be stopped, the sender is stopped
; and the stop count of its parent is decreased by 1.
; if the parent has stopped its child, an answer is sent to
; the parent in the buffer defined by the wait address of
; the child.
; call: return:
; w0 destroyed
; w1 destroyed
; w2 destroyed
; w3 link destroyed
b.i24 ; begin
w.g32:rs w3 i3 ;
rl w2 b18 ;
zl w0 x2+a138+1 ;
rl w3 x2+6 ; internal:=sender(buf);
sz w0 2.0000001 ; if io_operation(buf))
sh w3 -1 ; and internal>=0 then
jl (i3) ; begin
bz w0 x3+a12 ;
bs. w0 1 ; stop count(internal):=
hs w0 x3+a12 ; stop count(internal)-1;
i0: se w0 0 ; exam stop:
jl (i3) ; if stop count(internal)=0
bz w1 x3+a13 ; and state(internal)=wait stop
so w1 a105 ; then
jl (i3) ; begin
al w1 x1+a106 ; child state:=
hs w1 x3+a13 ; state(internal):=wait start;
rl w2 x3+a40 ; buf:=wait address(internal);
rl w3 x3+a34 ; internal:=parent(internal);
bz w0 x3+a12 ;
bs. w0 1 ; stop count(internal):=
hs w0 x3+a12 ; stop count(internal)-1;
se w1 a99 ; if child state<>wait start parent
jl i0 ; then goto exam stop;
; let the driver claim the buffer, so that
; it may send the answer:
rl w1 b21 ;
ac w0 x1 ; receiver(buf) := -cur; (i.e. claimed)
rs w0 x2+4 ;
bz w3 x1+a19 ; decrease(bufclaim(cur));
al w3 x3-1 ; (even if claims would be exceeded)
hs w3 x1+a19 ;
rl w1 x1+a17 ; answer area := first addr(cur);
al w0 1 ; result := 1;
jd 1<11+22; send answer;
jd (i3) ; return disabled;
i2: 0 ;
i3: 0 ;
e. ; end
; procedure exam sender(sender stopped)
; call: return:
; w0 unchanged
; w1 unchanged
; w2 unchanged
; w3 link link
b.i24 ; begin
w.g34:rs w3 i0 ;
am (b18) ;
rl w3 6 ; internal:=sender(buf);
sh w3 -1 ;
jl (i0) ; if internal<0
bz w3 x3+a13 ;
sz w3 a105 ; or state(internal)=stopped
jl (i0) ; then goto sender stopped;
rl w3 i0 ;
jl x3+2 ;
i0: 0 ;
e. ; end
; procedure check i-o transfer (document size, message);
;
; call return
; w0 size of document size of document
; w1 - unchanged
; w2 message message
; w3 link destroyed
;
g37: ;
jl. (+2) ; goto check i-o transfer;
d146 ;
; procedure follow chain(no. of slices,chain table index, slice)
; the return value is the chain table index of entry number <no.
; of slices> in the chain starting at <chain table index>
; call: return:
; w0 n.o.s. destroyed
; w1 unchanged
; w2 c.t.i. slice
; w3 link destroyed
b.i8
w.d74:rs w3 i3 ; save return
ac w3 (0) ;
as w3 1 ; count := -2 * no. of slices
jl. i2. ; goto test; repeat:
i0: sl w3 -30 ; if count >= -30
jl. x3+i1. ; then goto advance(-count)
ba w2 x2 ;
r. 16 ;
i1: al w3 x3+32 ; count := count + 32
i2: sh w3 -2 ; test: if count < 0
jl. i0. ; then goto repeat
jl (i3) ; return
i3: 0 ;
e. ;
; procedure test users , reserver, and writeprotecters(intproc,extproc);
; reg call return
; w0 undef
; w1 intproc unchanged
; w2 extproc unchanged
; w3 link result
; the procedure set result = 2.000001 if intproc is user
; = 2.000011 if intproc is reserver (and user)
; = 2.000101 if intproc and other ip are users
; = 2.000100 if there only are other users
; = 2.001100 if another ip is reserver (and user)
; = 2.01---- if intproc has writeprotected
; = 2.10---- if other(s) has writeprotected
; = 2.11---- if intproc and other(s) has writeprotected
; writeprotection bit can only be set if the extprocess is an areaprocess.
; of extproc else result is set to zero
b. i5,j5 w.
d76: ds. w3 j1. ; save(link,extproc);
rl w0 x2+a52 ; w0:=reserver.extproc;
al w3 2.10 ;
sn w0 (x1+a14) ; if intproc is reserver then
jl. i3. ; goto test other users;
al w3 0 ;
se w0 0 ; if there is another reserver then
al w3 2.1000 ; set other-reserver bit;
i3: ba w2 x1+a14 ; w2:=addr(bitpattern.intproc);
bz w0 x2 ; w0:= bitpattern.intproc;
sz w0 (x1+a14) ; if userbit.intproc is on then
al w3 x3+1 ; w3:=w3+1 <* set intproc is user *> else
al w2 a402 ;
i0: am. (j0.) ;
bz w0 x2 ; w0:=next pattern.userbittable;
sn w0 0 ; if no users then
jl. i1. ; goto f1;
hs w2 0 ;
sn w0 (x1+a14) ; if only intproc is user then
jl. i1. ; goto f1 else
al w3 x3+4 ; result:=result add 2.0100;
jl. i2. ; goto return;
i1: al w2 x2+1 ; w2:=next rel addr;
se w2 a402+a403 ; if not end bittable then
jl. i0. ; goto f0;
i2: rl. w2 j0. ; if extproc=area then
rl w0 x2+a10 ; begin
se w0 4 ;
jl. i5. ;
rs. w3 j0. ; <* save result *>
jl. w3 d114. ; check writeprotect(intproc, extproc);
jl. i4. ;+0: none:
am -2 ; j3;+2: intproc:
am -2 ; j4;+4: other(s):
rl. w0 j5. ;+6: intproc + other(s):
rl. w3 j0. ;
ea w3 1 ; <* add writeprotection bits *>
sz ; end;
i4: ;
rl. w3 j0. ;
i5: jl. (j1.) ; return;
j0: 0
j1: 0
j3: 2.010000 ; intproc
j4: 2.100000 ; other(s)
j5: 2.110000 ; intproc + other(s)
e.
; procedure check writeprotect(internal, proc);
; call return
; w0 - unchanged
; w1 internal unchanged
; w2 proc unchanged
; w3 link unchanged
;
; return: link + 0: no internal has writeprotected
; link + 2: only named internal has writeprotected
; link + 4: other than named internal has writeprotected
; link + 6: internal + other has writeprotected
;
b. i10, j10 w.
d114: ; begin
ds. w3 i3. ; save registers;
ds. w1 i1. ;
zl w0 x1+a14+1 ; <* save internal.idbit mask *>
rs. w0 i4. ;
ea w2 x1+a14 ;
al w2 x2+a404 ; <* save addr of id-bit element *>
rs. w2 i5. ;
rl. w3 i2. ;
al w2 x3+a405 ; <* w2: first writeprotect bit element,
al w3 x3+a250 ; w3: top of writeprotect bit array,
al w1 0 ; w1: state = <no internal has writeprotected> *>
j0: ; repeat begin
zl w0 x2 ; if element <> 0 then
sn w0 0 ; begin
jl. j2. ;
sn. w2 (i5.) ; if element.addr = int.bitelement and
so. w0 (i4.) ; element.bit(int.idbit) is on
jl. j1. ;
al w1 x1+ 2 ; then state := state and <int has writeprot>;
sn. w0 (i4.) ; if element.addr <> int.bitelement or
jl. j2. ; other than int.idbit is on
j1: sh w1 2 ; then state := state and <others has writeprot>;
al w1 x1+ 4 ; end;
j2: ; end until
al w2 x2+ 1 ; element = top element;
se w2 x3 ;
jl. j0. ;
;
dl. w3 i3. ; <* restore registers and
wa w3 2 ; modify return addr with state *>
dl. w1 i1. ;
jl x3 ; end;
;
0 ; save w0:
i1: 0 ; save w1: int
i2: 0 ; " " : proc
i3: 0 ; " " : link
i4: 0 ; id bit of internal
i5: 0 ; writeprotect id bit element addr in proc
e.
; procedure check user;
;
; call: w1=internal, w2=proc, w3=link
; exit: w0=undef, w1, w2, w3=unchanged
; return address: link+2: cur was user
; link : cur was not user
d102: ; begin
ba w2 x1+a14 ;
bz w0 x2 ; w0:=internal.userbit;
bs w2 x1+a14 ; reset w2;
sz w0 (x1+a14) ; if internal is user then
jl x3+2 ; return(link+2) else
jl x3 ; return(link);
; end;
; procedure check any reserver;
;
; call: w1=internal, w2=proc, w3=link
; exit: w0=undef, w1, w2, w3=unchanged
; return address: link : other process is reserver
; link+2: internal is reserver
; link+4: not reserved by anyone
d113: ; begin
rl w0 x2+a52 ; if proc.reserver=0 then
sn w0 0 ;
jl x3+4 ; return(link+4);
se w0 (x1+a14) ; if proc.reserver<>internal.idbit then
jl x3 ; return(link+0); <* other reserver *>
jl x3+2 ; return(link+2); <* internal reserver *>
; end;
; procedure insert writeprotect(internal, proc)
;
; call w1=internal, w2=proc, w3=link
; exit w0=undef, w1, w2, w3=unchanged
;
d118: ; begin
ea w2 x1+a14 ; element:=proc.userbit element;
zl w0 x2+a404 ; w0:=proc.writeprotect element;
lo w0 x1+a14 ; w0:=proc.writeprotect element or internal.idbit;
hs w0 x2+a404 ; proc.writeprotect element:=updated writeprotect element;
es w2 x1+a14 ;
jl x3 ; end;
; procedure remove writeprotect(internal, proc);
;
; call: w1=internal, w2=proc, w3=link
; exit: w0=undef, w1, w2, w3=unchanged
;
d119: ; begin
ea w2 x1+a14 ;
zl w0 x2+a404 ; element:=proc.userbitelement - displacement;
sz w0 (x1+a14) ; if element.bit(intproc.idbit) is on then
lx w0 x1+a14 ; element.bit(intproc.idbit):=0;
hs w0 x2+a404 ;
es w2 x1+a14 ;
jl x3 ; end;
; ****** indirect addressed monitor routines ******
; procedure conditional reschedule (eq d20)
; procedure unconditional reschedule (eq d21)
; conditional: if 'no fo free pu' = 0 the internal is rescheduled.
; call return
; w0 - destroyed
; w1 internal internal
; w2 - destroyed
; w3 link destroyed
;
b. i10 w.
d40: rl w2 (b59) ; conditional reschedule:
rl w2 x2 ; begin
se w2 0 ; if no of free pu > 0 then
jl x3 ; return;
;
d41: rs. w3 i3. ; unconditional reschedule:
al w0 a95 ;
jl w3 d9 ; deactivate process(internal, waiting for cpu);
sn w0 a95 ; if not internal.stopped then
jl w3 d10 ; link internal(internal);
jl. (i3.) ;
;
i3: 0 ;
e. ; end;
; procedure check and search name (=d17+d11 -> d67+d44) (eq d101)
;
; call: w1=cur, save w3(cur)=name, w3=link
; exit: w0, w1=unchanged, w2=name, w3=entry
; return address: link: entry not found
; link+2: entry found
; c29 : name area outside current process
b. i25 w.
d43: ;
ds. w1 i1. ; save(w0, cur);
rl w2 x1+a31 ; name:=save w3(cur);
al w0 x2+6 ;
sh w0 0 ; if overflow or
jl c29 ;
sl w2 (x1+a17) ; name<first addr(cur) or
sl w0 (x1+a18) ; name+6>=top addr(cur) then
jl c29 ; goto internal 3;
dl w1 x1+a43 ; w0w1:=catbase(cur);
jl. i14. ; goto search name(name, entry, base);
; the following procedures searches the name table for a given entry and delivers its entry in
; the name table. if name is undefined, the entry is name table end.
; procedure search name(name, entry); (eq d11)
; call: w2=name, w3=link
; exit: w0, w1, w2=unchanged, w3=entry
; return address: link : name not found, w3=(b7)
; link+2: name found
d44: ds. w1 i1. ; save(w0, w1);
am (b1) ;
dl w1 +a43 ; base:=catbase(cur);
i14: al w3 x3+1 ; link := link + 1; i.e. destinguish between normal and error return;
; procedure search name(name, entry, base); (eq d71)
; call: w0, w1=base, w2=name, w3=link
; exit: w0, w1=undef, w2=unchanged, w3=entry
; return address: link : name not found, w3=(b7)
; link : name found, w3 <> (b7)
d45: ds. w3 i3. ; save (name, return);
ds. w1 i20. ; save search base;
i4: al w1 x1-1;used ;
bs. w0 i4.+1 ;
ds. w1 i6. ; base:=base+(1, -1);
dl w1 d73 ;
ds. w1 i8. ; min base:=extreme;
rl w1 b7 ;
rs. w1 i9. ; found:=name table end;
rl w1 b1 ; get physical name address
b. h1 w. ; if mp then
am (b9) ;
h0=k
jl. 0 ; begin
gg w1 b104 ; get cur register;
c.(:h0+a8-k-1:)
am 0, r.(: h0+a8+2-k :)>1 ; fill up
z.
e. ; end mp
wa w2 x1+a182 ;
dl w1 x2+6 ;
ds. w1 i13. ; move name to last name in name table;
dl w1 x2+2 ;
sn w0 0 ; if name(0)<>0 then
jl. i18. ;
ds. w1 i11. ;
rl w3 b3 ; for entry:=name table start
jl. i17. ;
i15: dl. w1 i11. ;
i16: al w3 x3+2 ; step 2 until name table end do
i17: rl w2 x3 ;
sn w1 (x2+a11+2) ; begin
se w0 (x2+a11+0) ; proc:=name table(entry);
jl. i16. ;
dl. w1 i13. ;
sn w0 (x2+a11+4) ;
se w1 (x2+a11+6) ; if name.proc=name and
jl. i15. ;
sn. w2 (i21.) ;
jl. i18. ;
dl w1 x2+a49 ;
sl. w0 (i7.) ; lower.proc>=lower.min and
sl. w0 (i5.) ; lower.proc<=lower.base and
jl. i15. ;
sh. w1 (i8.) ; upper.proc<=upper.min and
sh. w1 (i6.) ; upper.proc>=upper base then
jl. i15. ; begin
ds. w1 i8. ; min:=interval.proc;
rs. w3 i9. ; found:=entry;
sn. w0 (i19.) ; if base.proc = search base
se. w1 (i20.) ; then goto found;
jl. i15. ; end;
i18: ; end;
dl. w0 i0. ; restore(w0, w1, w2);
dl. w2 i2. ; w3:=found;
sn w3 (b7) ; if w3=name table end then
jl. (i3.) ; return to link
am. (i3.) ; else
jl +1 ; return to link+1;
i9: 0 ;i0-2: found (i.e. current best entry, or (b7))
i0: 0 ;i1-2: saved w0
i1: 0 ;i2-2: saved w1
i2: 0 ;i3-2: saved w2
i3: 0 ; saved return
i5: 0 ;i6-2: lower base+1 for search
i6: 0 ; upper base-1 for search
i7: 0 ;i8-2: lower minimum
i8: 0 ; upper minimum
; the last entry in name table must point here:
c98 = k-a11
i10: 0 ; name to search for
i11: 0 ;
i12: 0 ;
i13: 0 ;
i19: 0 ; search base
i20: 0 ;
i21: c98 ;
e.
;
; procedure remove user(internal, proc); <* eq d123 *>
; procedure remove reserver(internal, proc); <* eq d124 *>
;
; removes the id-bit of the internal from the reserver and/or user fields.
;
; call return
; w0 - destroyed
; w1 internal internal
; w2 proc proc
; w3 link link
;
d53: ; remove user
ba w2 x1+a14 ; begin
zl w0 x2 ; if proc.userbits(internal.id-bit) is on then
sz w0 (x1+a14) ; proc.userbits(internal.id-bit) := 0;
bs w0 x1+a14+1 ;
hs w0 x2 ;
bs w2 x1+a14 ; if proc.reserver = internal then remove reserver;
; end;
;
d54: ; remove reserver
rl w0 x2+a52 ; begin
sn w0 (x1+a14) ; if proc.reserver = internal then
al w0 0 ; proc.reserver := 0;
rs w0 x2+a52 ;
jl x3 ; end;
; procedure insert reserver(internal, proc); <* eq d125 *>
; procedure insert user(internal, proc); <* eq d126 *>
; adds the id-bit of the internal to reserver-/user-fields of proc.
;
; call return
; w0 - destroyed
; w1 internal internal
; w2 proc proc
; w3 link link
;
d55: ; insert reserver
rl w0 x1+a14 ; begin
rs w0 x2+a52 ; proc.reserver := internal.id;
; goto insert user;
; end;
;
d56: ; insert user
ba w2 x1+a14 ; begin
zl w0 x2 ;
lo w0 x1+a14 ; proc.idbit(internal.id) := 1;
hs w0 x2 ;
bs w2 x1+a14 ;
jl x3 ; end;
; procedure claim buffer(cur, buffer); <* eq d108 *>
;
; call return
; w0 - destroyed
; w1 cur cur
; w2 buffer buffer
; w3 link link
;
b. i0 w.
d58: ; claim buffer
zl w0 x1+a19 ; begin
sn w0 0 ; if cur.bufferclaim <> 0 then
jl. i0. ; begin
bs. w0 1 ; cur.bufferclaim := cur.bufferclaim - 1;
hs w0 x1+a19 ;
ac w0 (x2+a141) ; buffer.receiver := -buffer.receiver;
rs w0 x2+a141 ;
jl x3 ; <* ok return *>
; end
i0: ; else
rs w0 x1+a30 ; begin cur.saved w2 := 0;
jl c99 ; goto return from interrupt;
; end;
e. ; end;
; procedure regretted message(buffer); <* eq d75 *>
; simulates the release of a messge buffer, as in wait answer. the bufferclaim
; of the sender is increased. the buffer is removed and released (unless in
; state = received).
;
; call return
; w0 - unchanged
; w1 - unchanged
; w2 buffer buffer
; w3 link destroyed
;
b. i10, j10 w.
d65: ; regretted message
rs. w3 i3. ; begin
ds. w1 i1. ;
rl w1 x2+a142 ;
sh w1 0 ; if message.sender < 0 then exit; <* buffer already regretted *>
jl. j6. ;
ac w0 x1 ; message.sender := -message.sender; <* indicates message regretted *>
rs w0 x2+a142 ;
rl w0 x1+a10 ; if sender.kind = pseudo proc or
se w0 64 ; sender.kind = csp_terminal then
sn w0 q8 ; sender:= sender.main;
rl w1 x1+a50 ;
sz w0 -1-64 ; if sender.kind<>internal and sender.kind<>pseudo then
rl w1 x1+a250 ; sender := sender.driverproc;
;
zl w3 x1+a19 ; sender.bufferclaim := sender.bufferclaim + 1;
al w3 x3+1 ;
hs w3 x1+a19 ;
;
rl w1 x2+a141 ; receiver := abs(message.receiver);
sh w1 0 ;
ac w1 x1 ; if receiver < 5 then
sh w1 5 ; goto remove and release;
jl. j5. ; <* message contains an answer *>
;
rl w0 x1+a10 ; if receiver.kind <> internal and
rl w3 x1+a250 ; receiver.kind <> pseudo and
se w0 0 ; receiver.driverproc < 0 then
sn w0 64 ; begin
sz ; <* ida/ifp process - receiver driven by monitor *>
sl w3 0 ;
jl. j2. ;
;
j0: sn w0 q20 ; proc := receiver;
jl. j1. ;
sn w0 q26 ;
jl. j1. ; while proc.kind <> main do
rl w1 x1+a50 ; proc := proc.main;
rl w0 x1+a10 ;
jl. j0. ;
;
j1: al w3 2.1000 ; if message.state = stopped then
zl w0 x2+a138+1 ; return
sz w0 x3 ; else
jl. j6. ; message.state := stopped;
lo w0 6 ;
hs w0 x2+a138+1 ;
;
sn w2 (x1+a81) ; if message = main.waiting_queue.first then
jl. j6. ; return;
jl w3 d5 ; unlink(message);
al w0 1 ;
jl. d142. ; test ready and setup(message,force));
; <* it will exit with return from interrupt - the
; setup procedure of the receiver will take care
; of a proper action on the regretted message *>
; end;
j2: ; <* receiver is not an subprocess *>
rl w1 x2+a141 ; if message.claimed then
sl w1 0 ; begin
jl. j3. ;
se w0 q20 ;
sn w0 q26 ; if receiver.kind = main then
sz ;
jl. j6. ; begin
al w3 2.1000 ;
zl w0 x2+a138+1 ; if message.state = stopped then
sz w0 x3 ; return; <already stopped>
jl. j6. ;
lo w0 6 ; message.state := stopped;
hs w0 x2+a138+1 ;
ac w1 x1 ; if message = main.waiting_queue.first or
se w2 (x1+a81) ; not message.in_queue then
sn w2 (x2+a140) ; return
jl. j6. ; else begin
jl w3 d5 ; unlink(message);
al w0 1 ;
jl. d142. ; test ready and setup(message,force);
; end;
; end
; else return;
; end;
j3: ; <* the message is neither answer nor claimed *>
se w0 0 ; if receiver.kind = internal or
sn w0 64 ; receiver.kind = pseudo then
jl. j5. ; goto remove and release;
se w0 4 ; if receiver.kind = area then
jl. j4. ;
rl w1 x1+a50 ; receiver := receiver.main.main; <* physical disc proc *>
rl w1 x1+a50 ;
j4: se w2 (x1+a54) ; if receiver.event_q.first = message then
jl. j5. ; begin
al w0 -1 ;
wa w0 x1+a56 ; if receiver.interrupt_addr is even then
sz w0 2.1 ; receiver.interrupt_addr:=receiver.intterupt_addr-1;
rs w0 x1+a56 ; end;
;
j5: jl w3 d106 ; remove and release(message);
;
j6: dl. w1 i1. ; exit:
jl. (i3.) ; return;
;
i0: 0 ; saved registers
i1: 0 ;
i3: 0 ;
;
e. ; end;
; procedure move message(from, to); <* eq d14 *>
; moves 8 words (message or answer) from a given storage address to another.
;
; call return
; w0 - destroyed
; w1 from from
; w2 to to
; w3 link destroyed
;
b. i0 w.
d64: ; move message
rs. w3 i0. ; begin
dl w0 x1+2 ;
ds w0 x2+2 ; <* move the words *>
dl w0 x1+6 ;
ds w0 x2+6 ;
dl w0 x1+10 ;
ds w0 x2+10 ;
dl w0 x1+14 ;
ds w0 x2+14 ;
jl. (i0.) ;
;
i0: 0 ;
;
e. ; end;
; procedure check mess area and name (save w3) area;
; procedure check name (save w3) area;
; procedure check name (save w2) area;
; call return
; w0 - destroyed
; w1 cur cur
; w2 - name
; w3 link link
d66: ; check message area and name area:
rl w2 x1+a29 ; begin
al w0 x2+14 ; mess := cur.save w1;
sh w0 0 ; if overflow or
jl c29 ; mess < cur.first address or
sl w2 (x1+a17) ; mess >= cur.top address then
sl w0 (x1+a18) ; goto internal 3;
jl c29 ;
d67: ; check name (save w3) area:
am a31-a30 ;
d115: ; check name (save w2) area:
rl w2 x1+a30 ;
al w0 x2+6 ;
; continue with d116!
; procedure check within (first, last);
; checks taht the specified area is within the process
; call return
; w0 last last
; w1 cur cur
; w2 first first
; w3 link link
; return: link: within process
; c29 : not within
d116: ; check within:
sh w0 0 ; if overflow or
jl c29 ; first < cur.first address or
sl w2 (x1+a17) ; last >= cur.top address then
sl w0 (x1+a18) ; goto internal 3;
jl c29 ;
jl x3 ; end;
; procedure check message area and buf
; call return
; w0 - destroyed
; w1 cur cur
; w2 - buf
; w3 link link
; return: link: ok
; c29 : mess area outside cur
; c29 : buf not message buf
d117: ; check message area and buf:
rl w2 x1+a29 ; begin
al w0 x2+14 ; mess := cur.save w1;
sh w0 0 ; if overflow or
jl c29 ; mess < cur.first address or
sl w2 (x1+a17) ; mess+14 >= cur.top address then
sl w0 (x1+a18) ; goto internal 3;
jl c29 ;
; continue with check message buf
; procedure check message buf;
; checks whether the save w2 of the internal process is a mess buf addr.
; call return
; w0 - destroyed
; w1 internal cur
; w2 - buf
; w3 link link
; return: link: buffer ok
; c29 : save w2 not mess buf
b. i0 w.
d68: ; check message buf:
rl w2 x1+a30 ; buf := internal.sawe w2;
sl w2 (b8+4) ; if buf < mess buf pool start or
sl w2 (b8+6) ; buf >=mess buf pool top then
jl c29 ; goto internal 3;
al w1 x2 ;
ws w1 b8+4 ; if (buf-poolstart-4) modulo size of message <> 0
al w1 x1-a7 ; then goto internal 3;
al w0 0 ;
wd w1 b8+8 ;
rl w1 b1 ; w1 := cur
sn w0 0 ;
jl x3 ; return
jl c29 ;
e. ; end;
; procedure check event (proc, buf);
; checks that buf is the address of an operation in the event queue of the internal process
; call return
; w0 - destroyed
; w1 proc proc
; w2 buf buf
; w3 link link
; return: link: buffer address ok
; c29 : buf is not in the queue
b. i0 w.
d69: ; check event:
al w0 x2 ; begin
al w2 x1+a15 ; oper := proc.next;
i0: rl w2 x2+0 ; next: oper := oper.next;
sn w2 x1+a15 ; if oper = proc.eventq then
jl c29 ; goto internal 3; <*not in queue*>
se w0 x2 ; if buf <> oper then goto next;
jl. i0. ;
jl x3 ; return;
e. ; end;
; external interrupt entry:
;
; when an external interrupt occurs, or when 'user exception first'
; or 'user escape first' are zero, the cpu will save all registers
; in the current process descrition.
; exit is made to here with:
; w2 = 2 * interrupt number
; ex = 0
b. i3 w.
c1: al w1 x2 ; interruptstat(intno) :=
ls w1 1 ; interruptstat(intno) + 1;
wa w1 b79 ;
rl w0 x1+2 ;
ba. w0 +1 ;
rs w0 x1+2 ;
se w0 0 ;
jl. i3. ;
rl w0 x1+0 ; <* count in double words *>
ba. w0 +1 ;
rs w0 x1+0 ;
i3: ;
wa w2 b0 ;
rl w1 b51 ; w1 := current process
sh w1 0 ; if cur defined then
jl. c3. ; begin
rs w1 b1 ; process in monitor := cur;
al w0 1 ; if rescedule count.cpuno > max then
al w3 0 ; rescedule process
b. h1 w. ;
am (b9) ;
h0=k ;
jl. 0 ;
gg w3 b108 ;
c. (:h0+a8-k-1:) ;
am 0, r.(:h0+a8+2-k:)>1;
z.
e. ;
ds. w2 i2. ;
wa w0 x3+b83 ; if reschedule count > max or
rs w0 x3+b83 ; internal.state <> running
zl w3 x1+a13 ; then
sh w0 a83 ; unconditional reschedule
se w3 a94 ; else
am d21-d20; conditional reschedule;
jl w3 d20 ;
dl. w2 i2. ;
jl. c3. ; switch out through interrupt-table;
i1: 0 ; saved proc
i2: 0 ; saved intno
e.
; monitor call entry:
;
; if the current process executes a montor call, the cpu will
; save all the registers in the current process description.
; exit is made to here with:
; w1 = top register dump
; w2 = monitor function
; ex = 0
c0: rl w1 b51 ;
rs w1 b1 ; process in monitor := cur;
zl w0 x1+a13 ; if internal.state =waiting for stop then
so w0 a105 ; begin
jl. c7. ;
jl w3 d9 ; deactivate process
rl w2 x1+a33 ; internal.ic := internal.ic - 2
al w2 x2-2 ;
rs w2 x1+a33 ; (repeat monitor call later if started)
jl c99 ;
c7: al w3 x2 ; moncalltable(call no) :=
ls w3 -1 ; moncalltable(call no) + 1;
ls w3 +2 ; <* make odd calls even *>
wa w3 b81 ;
rl w0 x3+2 ;
ba. w0 +1 ;
rs w0 x3+2 ;
se w0 0 ;
jl. c3. ;
rl w0 x3+0 ;
ba. w0 +1 ; <* count in double words *>
rs w0 x3+0 ;
c3: am. (+4) ; switch out through monitor procedure entry table;
jl (x2+0) ;
b16 ; <*address of monitor entry table*>
; second level external interrupt entry:
;
; exit is made to here with:
; w1 = top register dump
; w2 = 2 * interrupt number
c8:
sn w2 2*7 ; if clock interrupt then
ri a179 ; exit to monitor;
sn w2 2*6 ; if cause = powerfail then
jl. c6. ; goto power fail routine;
jl -3<1 ; halt;
; program errors in the current process are transferred to here,
; (as external interrupts):
;
; w1 = cur
c2: ; internal interrupts, overflow, spill, escape errors:
; monitor bugs (i.e. exception- or escape-addresses
; outside write-limits of process)
c4: ; bus error in operand transfer: (no strategy yet)
c5: ; bus error in instruction fetch: (- - - )
jl w2 (b31) ; call errorlog
al w0 a96 ; state := running after error;
al w3 c99 ;
zl w2 x1+a13 ; if process active then
se w2 a95 ; deactvate process (and return)
jl d9 ;
hs w0 x1+a13 ; else begin
al w2 x1+a16 ; process.state := running after error;
al w3 c99 ; unlink proc from active queue
jl d5 ; end; return
; power failure:
;
; may occur at any level
;
; save the current interrupt stack entry address, unless
; already saved
; (this should prevent powerfail-cascades from disturbing the system)
b. h10, i10 w. ;
c6: gg w2 b91 ; w2 := current stack element;
rl. w3 h0. ; w3 := previous power up element;
sn w3 0 ; if previous element is free then
rs. w2 h0. ; power up element := current stack element;
al w2 0 ; ilevc := 0;
gp w2 b90 ; (i.e. the following will provoke a systemfault)
jl -1<1 ; halt;
h0: b49 ; power up element: initially monitor element
; power up:
;
; initialize: montop (i.e. max monitor function)
; size (i.e. core size)
; inf (i.e. power up element)
;
; initialize pu information table and if the pu is a mp then start all remaining cpus.
; clear any pending interrupt bits, because they may be irrellevant
;
; entry conditions:
; inf register = 1
; totally disabled
c25: al w3 -1<11 ; montop := 1 < 11
ac w3 x3+b17 ; - top monitor function number;
gp w3 b93 ;
rl w2 b59 ; pu inf table.montop := montop;
rs w3 x2+a352 ;
rl w3 b12 ; size := number of storage bytes;
gp w3 b92 ;
rs w3 x2+a353 ; pu inf table.size := size;
am +12 ;
al w3 b49 ;
rs w3 x2+a351 ; pu inf table.inf := inf;
rl w3 b9 ;
sn w3 a8 ; if pu kind = mp then
jl. i3. ; begin
rl w3 x2+a350 ; iopu.pu tabel register := pu inf table.pu tabel;
gp w3 b105 ;
rl w3 x2+a354 ; iopu.exofs register := pu inf table.exception offset;
gp w3 b106 ;
rl w3 x2+a355 ; iopu.dmofs register := pu inf table.dump offset;
gp w3 b107 ;
;
; start all remaining cpus
al w0 1 ; no of cpues := 1;
rs w0 b82 ;
al w0 a194 ; interruptlevel := 8; <*start pu*>
rl w1 b67 ; for i := 1 step 1 until max dev do
i5: al w1 x1+a314 ; if controllertabel(i).chpadr = pu inf tabel then
sl w1 (b68) ; begin <*pu-element*>
jl. i2. ;
rl w3 x1+a310 ;
se w3 (b59) ;
jl. i5. ; puaddr := (controllertabel(i) -
rl w3 b82 ;
al w2 x1 ; controllertabel(0)) * 8 and (1 shift 23);
ws w2 b67 ;
lo w2 g49 ;
do w0 x2 ; start pu(puaddr, interruptlevel);
sx 2.111 ; if pu is started then
sz ;
ba. w3 1 ; no of cpues := no of cpues + 1;
rs w3 b82 ;
jl. i5. ; end;
; end;
i3: ; else
al w0 0 ; set free pu := 0
rs w0 (x2) ; (* always rescedule when external interrupt *)
i2: ;
c.(:a90>0 a.1:)-1
al. w3 i1. ; dump core via fpa
jl. (2) ;
d140 ;
i1: ;
z.
al w3 6 ; ilevc := 0 < 12 + 6;
gp w3 b90 ; i.e. enable for powerfail;
rl. w3 h0. ; w3 := power up element;
sn w3 0 ; if power up element = 0 then
jl -2<1 ; halt; i.e. power fail was not serviced;
rs w3 b75 ; after powerfail := true;
; (should be tested by clockdriver)
rl w2 b73 ; intno := max external interrupt number;
i0: gp w2 b95 ; rep: clear (intno) in cpu;
al w2 x2-1 ; intno := intno - 1;
sl w2 6+1 ; if intno > powerfail then
jl. i0. ; goto rep;
al w1 0 ; (prepare a new h0...)
je. +2 ; (if any power fail during this start up,
jd. +2 ; it will be 'serviced' now, i.e. systemfault)
; the following sequence of instructions have to be executed
; without any disturbance, else the system won't work
rs. w1 h0. ; clear previous power up element;
; (i.e. prevent two consecutive powerups)
gp w3 b91 ; inf := power up element;
ri a179 ; return interrupt;
; (the limit-copies must be initialized)
e. ; end of power fail/restart
; parameter errors in monitor call:
;
; all monitor procedures check that the parameters are
; within certain limits.
; if the parameters are wrong, the calling process is break'ed.
;
; (all regs irrellevant)
b. j10 w. ;
; definitin of exception regdump:
j0 = a29 - a28 ; w0, w1
j1 = a31 - a28 ; w2, w3
j2 = a33 - a28 ; status, ic
j3 = a177- a28 ; cause, sb
a180 = j3 + 2 ; top of exception regdump = new rel ic
j4: c2 ;
c28 : ; internal 3:
rl w1 b1 ;
rs w3 x1+a339 ; make footprint!
al w3 6 ;
rs w3 x1+a176 ; cause (cur) := 6; i.e. monitor call break;
rl w2 x1+a27 ; w2 := exception address (cur);
sn w2 0 ; if exception address = 0 then
jl. (j4.) ; goto internal interrupt;
al w3 x2 ; save w2 and
jl w2 (b31) ; call errorlog
al w2 x3 ; restore w2
wa w2 x1+a182 ; w2 := abs exception address;
dl w0 x1+a29 ; move: save w0
ds w0 x2+j0 ; save w1
dl w0 x1+a31 ; save w2
ds w0 x2+j1 ; save w3
dl w0 x1+a33 ; save status
ds w0 x2+j2 ; save ic
; rs w0 x1+a28 ; save w0 := save ic;
; al w0 14<2+0 ;
; rs w0 x1+a29 ; save w1 := 'jd'-instruction;
dl w0 x1+a177 ; save cause (= 6)
ds w0 x2+j3 ; save sb to user exception addres;
; rs w0 x1+a30 ; save w2 := save sb;
; rs w3 x2+a31 ; save w3 := save cause (= 6);
ws w2 x1+a182 ; w2 := logic user exception address;
al w2 x2+a180 ;
rs w2 x1+a33 ; save ic := exception address + no of regdump bytes
jl c99 ; goto interrupt return
e. ;
; answer device operation
;
; the controller has delivered an answer to a 'device operation'
; message. prepare the RC8000/RC9000 answer
;
; call
; w0 result
; w1 main
; w2 -
; w3 function < 1
b. i10, j30 w. ; answer device operation
c47: ; begin
ds. w1 i1. ;
al w0 x3 ;
jl. w3 d156. ; decrease no_of_outstanding;
rl w2 x1+a501 ; message := main.message_buffer;
rl. w3 i6. ;
sl w3 5 ; if result >= 5 then
jl -1 ; panic;
rl. w0 i6. ;
ls w0 9 ; message.state.result:=
lo w0 x2+a138 ; message.state.result or last_result;
hs w0 x2+a138+1 ;
ls w3 +1 ; case result of
jl. (x3+j5.) ;
;
j5: -1 ; 0 ; -
j6 ; 1 ; ok
-1 ; 2 ; -
j15 ; 3 ; unintelligible
j15 ; 4 ; malfunction
;
j6: ; ok:
; -----
zl w0 x2+a138+1 ; begin
al w3 2.0100000 ;
sz w0 x3 ; if message.state.answer = 0 then
jl. j7. ; begin
;
lo w0 6 ; message.state := message.state or answer;
hs w0 x2+a138+1 ;
dl w0 x1+a520+a151 ; <* move answer from main.mess_0 - mess_7
ds w0 x2+a151 ; to message.mess_0 - mess_7 *>
dl w0 x1+a520+a153 ;
ds w0 x2+a153 ;
dl w0 x1+a520+a155 ;
ds w0 x2+a155 ;
dl w0 x1+a520+a157 ;
ds w0 x2+a157 ;
;
jl. j9. ; end
j7: ; else
; begin
rl w3 x1+a520+a150 ; if not statuserror then
sn w3 0 ; begin
sz w0 -1024 ; if result=1 then
jl. j4. ; begin
rl w0 x1+a520+a152 ;
wa w0 x2+a152 ; message.octet_count :=
rs w0 x2+a152 ; message.octet_count + main.mess_2;
j4: ; end;
; end;
rl w0 x2+a150 ; <* w3 = new status *>
sn w0 0 ; if old statuserror then
rs w3 x2+a150 ; skip new status;
rl w0 b219 ;
la w0 x1+a500 ; check := main.gen_info.check;
sn w0 0 ; if check then
jl. j8. ; begin
;
rl w0 x1+a520+a150 ; <* move mess_0, mess_3 - mess_7 to
rs w0 x2+a150 ; message *>
dl w0 x1+a520+a154 ;
ds w0 x2+a154 ;
dl w0 x1+a520+a156 ;
ds w0 x2+a156 ;
rl w0 x1+a520+a157 ;
rs w0 x2+a157 ;
j8: ; end <* check = 0 *>
j9: ; end
jl. j18. ;
; end <* ok *>
;
j15: ; unintelligible:
; malfunction:
; ---------------
al w0 2.0100000 ; begin
lo w0 x2+a138 ;
hs w0 x2+a138+1 ; message.state := message.state or answer;
;
; al w0 0 ; message.octet_count := 0;
; rs w0 x2+a152 ;
;
jl. j18. ; end <* unintelligible, malfunction *>
;
;
j18: ; common:
; -------
; begin
; ------> 8000 special <------
rl w3 x1+a235 ;
rl w0 x1+a10 ; device_address := main.device_address;
al w1 2 ;
se w0 q26 ; if main.kind <> ifp then
am 2.11<1 ; answer_device(normal)
do w1 x3+0 ; else
rl. w1 i1. ; answer_device(ifp);
; ------> end 8000 special <------
zl w0 x2+a138+0 ; <* don't use com_area any more *>
bs. w0 1 ;
hs w0 x2+a138+0 ; message.count := message.count - 1;
;
al w3 2.0000100 ;
la w3 x2+a138 ; if message.count = 0 and
sn w0 0 ; message.state = transfer_completed then
sn w3 0 ; begin
jl. j25. ;
;
rl w3 x2+a141 ; if message.receiver <> 2 then
sn w3 2 ; begin
jl. j20. ; <* if message was sent to an area which is
sh w3 0 ; removed during the operation a result 2
ac w3 x3 ; is inserted in the message *>
se w3 (x3+a50) ; if receiver.main = receiver then
jl. j19. ; begin <* receiver is a mainprocess *>
rl w3 b21 ; driverproc := receiver.driverproc;
zl w0 x3+a19 ; driverproc.buffer_claim :=
ba. w0 1 ; driverproc.buffer_claim + 1;
hs w0 x3+a19 ; end;
j19: ;
se w2 (x1+a200) ; if message = main.prepare_dump_message then
jl. j20. ; begin
rl w2 x1+a201 ;
rl w1 b21 ;
jl w3 d124 ; remove_reserver(driverproc, main.dump_device);
al w0 0 ;
rl. w1 i1. ;
rs w0 x1+a200 ; main.prepare_dump_message := 0;
rs w0 x1+a201 ; main.dump_device := 0;
; end;
; end;
j20: ;
zl w0 x2+a138+1 ; if message.state.io then
so w0 2.0000001 ; begin
jl. j22. ;
jl w3 d132 ; decrease_stopcount(message);
rl. w1 i1. ;
rl w2 x1+a501 ;
;
dl w0 x2+a152 ;
se w0 0 ;
se w3 0 ;
jl. j22. ;
es. w0 1 ; if message.hw_transfered = 0 and
wd w0 g48 ; message.bytecount <> 0 then
ea. w0 1 ; mess.hw :=(((mess.bytes-1)/3)+1)*2
ls w0 1 ;
rs w0 x2+a151 ; end;
j22: ;
; rl. w0 i6. ;
zl w0 x2+a138+1 ;
sh w0 8.1777 ; if result=ok then
jl. j23. ; goto result1
sz w0 -2048 ; if intervention then
am 1 ; result:=4;
am 2 ; else result:=3;
j23: al w0 1 ; result1: result:=1;
jl. w3 d15. ; deliver_answer(message);
; end;
j25: ;
jl. j30. ; end;
;
i6: 0 ;-2: result
i1: 0 ; 0: save main
; end;
; deliver interrupt to itc-main
; sets io result = 0 and continues with deliver interrupt
c48:
c.l53 b. f4 w. ; ****** test 41 ******
rs. w3 f1. ;
al w1 x2-a241 ;
rs. w1 f0. ;
jl. w3 (f3.) ;
41 ;
f0: 0 ; main
f1: 0 ;
jl. f2. ;
al w0 x1+a500 ; dump main.communication area
al w1 x1+a517 ;
jl. w3 (f4.) ;
jl. f2. ;
f3: d150 ;
f4: d151 ;
f2: ;
e.z. ; ****** end test 47 ******
al w2 x1+a242 ;
se w2 (x2) ; if in queue then
jl w3 d5 ; remove from queue
al w0 0 ; io result 0
al w3 c99 ;
jl d121 ; got to deliver interrupt and goto reutrn from interrupt
j30: rl. w1 i1. ;
rl w0 x1+a78 ;
so w0 2.010000 ; if not busy then
jl c42 ; continue with check main queue
jl c99 ; else goto return from interrupt;
e.
▶EOF◀