Trailing-Edge
-
PDP-10 Archives
-
BB-BT99V-BB_1990
-
10,7/mon/datman.mac
There are 9 other files named datman.mac in the archive. Click here to see a list.
TITLE DATMAN - DATA BASE MANAGER V201
SUBTTL D BLACK/DAL/JBS 02-OCT-90
SEARCH F,S
$RELOC
$CSUB ;ENTIRE MODULE IN COMMON PSECT
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1973,1988>
XP VDATMN,201
ENTRY DATMAN
DATMAN::! ;CAUSE DATMAN TO LOAD IF IN LIBRARY FILE
XP LISTSN,1 ;CAUSE S.MAC AND F.MAC TO BE LISTED HERE
; (USED TO BE IN COMMON WHICH IS NOW TOO BIG).
REPEAT 0,<
The DATA BASE MANAGER contains both subroutines to manipulate
monitor's data base and formats of various components of the data base.
The DATA BASE MANAGER should be the only module which modifies the data base;
all other modules should call DATMAN.
This scheme has a number of advantages:
1. It provides a good chance for comments.
2. It provides good conventions for future growth.
3. It provides good locality.
4. It helps reentrancy by having only one module maintain impure code.
DATMAN will also control writing in users' core too.
PROCESS and SEGMENT are important components in the data base
being introduced at this time.
A SEGMENT is one logical collection of data, either program data
or code, and is the building block of a program. Segments are really
the same as previously.
A PROCESS is a virtual machine;
it has a hardware state associated with it: a virtual memory, a processor,
typically one PC, a stack, etc. A process's virtual memory will
contain a number of segments. Several processes may run either
serially or in parallel as one overall program or user.
Monitor data will be organized on a per segment and a per process basis.
Part of per segment and part of per process data must be resident,
other parts could be swappable; the data breaks up
into four components. The following abbreviations and definitions will be used:
PRB Process Resident Block - the resident process information.
This will be very small, about 8 or 12 words.
PDB Process Data Block - the not necessarily resident (swappable) process data.
This will be most of the process data and may grow to fill a page or more.
SRB Segment Resident Block - the resident segment information.
This will be very small, about 8 or 12 words.
SDB Segment Data Block - the not necessarily resident segment data.
This may grow to fill a page or more.
Conventions about symbols:
symbols will consist of a three letter prefix and a three letter suffix.
The prefix will determine to what type of data base component the entry belongs,
and the particular usage of the entry.
For example, a word entry in the PDB would be .PDxxx.
The suffix is a three letter mnemonic describing the entry. Thus
the PDB entry SIZ containing the size of the PDB
would be .PDSIZ.
DATMAN is organized in the following manner:
First are the definitions of the various data base components.
These will be in alphabetical order so they can be found easily.
Second are subroutines for manipulating the data base,
grouped by function. Code should go down the page,
as in 5 series monitor conventions, until concern for locality
becomes more important.
> ;END REPEAT 0
SUBTTL PDB LOGIC
;SUBROUTINE TO FIND A PDB OR HALT
;CALL WITH:
; MOVE J,PROCESS-NUMBER
; PUSHJ P,FNPDBS
; RETURN HERE WITH W POINTING TO A PDB
;
FNDPDS::JUMPL J,NPJSTP
HRRZ W,JBTPDB##(J) ;GET PDB
CAIG J,JOBMAX## ;LEGAL JOB #
JUMPN W,CPOPJ## ;RETURN IF PDB EXISTS
NPJSTP::STOPCD .,STOP,NPJ, ;++NO PDB FOR JOB
;SUBROUTINE TO FIND PDB FOR PROCESS IN T1
; PUSHJ P,FPDBT1
; HERE IF NO PDB
; HERE WITH T1 POINTING TO PDB
;RETURNS WITH T1 UNCHANGED IF NO PDB
FPDBT1::PUSH P,J ;SAVE J AND W
PUSH P,W ; ..
HRRZ J,T1 ;COPY PDB HANDLE
PUSHJ P,FNDPDB ;FIND THE PDB
SOSA -2(P) ;CAUSE NON-SKIP RETURN
MOVE T1,W ;COPY CORE ADDRESS
POP P,W ;RESTORE AC'S
JRST JPOPJ1## ;RETURN
;SUBROUTINE TO FIND A PDB
;CALL WITH:
; MOVE J,PROCESS-NUMBER
; PUSHJ P,FNDPDB
; RETURN HERE IF NO PDB (W = 0)
; RETURN HERE WITH W POINTING TO PDB
FNDPDB::PUSH P,T1 ;SAVE T1
PUSHJ P,LGJPR1 ;SEE IF A LEGAL PROCESS (INCLUDING ZERO)
JRST TPOPJ## ;NOT, LOSE
HRRZ W,JBTPDB##(J) ;GET PDB ADDRESS
JUMPN W,TPOPJ1## ;IF W IS NON-ZERO GIVE THE SKIP RETURN
JRST TPOPJ## ; ELSE FAIL
SUBTTL CX RESOURCE ROUTINES
;ROUTINES TO MANIPULATE THE CX RESOURCE FOR A JOB. THE CX RESOURCE IS USED
;TO INTERLOCK PDB OR CONTEXT BLOCK REFERENCES.
;UPCX TO GET THE CX RESOURCE FOR THE JOB IN T1 (.CPJOB CONTAINS OUR JOB)
;UPCX WILL BLOCK IF THE REQUESTED CX RESOURCE ISN'T AVAILABLE
UPCX:: PUSH P,T2 ;SAVE EVERYTHING
PUSH P,J ;SAVE J
MOVE J,.CPJOB##
SKIPN T2,T1 ;WHO WE WANT
SOS T2 ;IF JOB 0, SAY -1
HRLM T2,JBTCX##(J) ;FLAG WHO WE WANT/OWN
JUMPE T1,UPCXR ;NO REAL INTERLOCKING FOR JOB 0
SYSPIF ;GUARD RACES
HRRZ T2,JBTCX(T1) ;GET THE OWNER OF HIS CX RESOURCE
JUMPN T2,CXWAIT ;WAIT IF IT ISN'T AVAILABLE
HRRM J,JBTCX##(T1) ;WE OWN HIS CX
SYSPIN
UPCXR: POP P,J
JRST T2POPJ## ;RETURN
CXWAIT: SYSPIN
MOVEI T2,CXQ## ;THE QUEUE
DPB T2,PJBSTS## ;SAY IN CX WAIT
POP P,J ;RESTORE J
POP P,T2 ;RESTORE T2
PJRST WSCHED## ;WAIT FOR RESOURCE
;HERE TO TRY AND GET CX RESOURCE AT INTERRUPT LEVEL. RETURN CPOPJ1
;IF WE HAVE IT, CPOPJ OTHERWISE. CALLER'S RESPONSIBILITY TO WAIT
GETCX:: PUSH P,T1 ;SAVE T1
SYSPIF
HRRZ T1,JBTCX##(J) ;GET OWNER OF CX RESOURCE WE DESIRE
JUMPN T1,GETCXR ;OWNED BY SOMEONE ELSE
MOVEM J,.CPCXJ## ;SAVE WE OWN IT
SKIPN J ;JOB 0?
SOSA .CPCXJ ;YES, FLAG OWN NUL JOB
HLLOS JBTCX##(J) ;SAY A CPU OWNS IT
AOS -1(P) ;GIVE GOOD RETURN
GETCXR: SYSPIN
JRST TPOPJ##
;COROUTINE TO GET AND GIVE THE CX RESOURCE (UUO LEVEL)
GGVCX:: PUSHJ P,UPCX ;GET CX RESOURCE
POP P,(P)
PUSHJ P,@1(P) ;CALL BACK
CAIA
AOS (P)
; PJRST DWNCX ;(FALL INTO DWNCX)
;HERE TO RELEASE THE CX RESOURCE WE (THE JOB IN J) OWNS
;CALL GIVCX FOR INTERRUPT LEVEL (OWNED BY CPU), OR
;DWNCX *FOR UUO LEVEL ONLY* (OWNED BY JOB IN .CPJOB)
DWNCX:: PUSH P,J ;SAVE J
PUSH P,F ;SAVE F
MOVE J,.CPJOB## ;GET JOB WHO IS RUNNING
SYSPIF ;INTERLOCK
HLRE F,JBTCX##(J) ;GET WHO WE OWN
HRRZS JBTCX##(J) ;WE NO LONGER OWN HIM
DWNCX1: SKIPL F ;IF OWNED NUL JOB
HLLZS JBTCX##(F) ;HE IS NO LONGER OWNED
SYSPIN
JUMPL F,DWNCXR ;RETURN IF NUL
SETZ F, ;**NO EVM**
PUSHJ P,[PUSH P,T1 ;SAVE T1
PUSH P,J ;AND J
PJRST SRFRCX##]
DWNCXR: POP P,F
POP P,J
POPJ P,
GIVCX:: PUSH P,J ;SAVE J
PUSH P,F ;SAVE F
SETZB F,J ;GET & CLEAR
SYSPIF
EXCH F,.CPCXJ## ;GET JOB
JRST DWNCX1
;HERE TO UNWIND CX RESOURCE AT SCHEDULAR LEVEL
;CALL WITH JOB WHOSE CX WE WANT IN J, RETURN WITH OWNER (IF ANY) IN T3
UNWCX:: HLRE T3,JBTCX##(J) ;WHO WE WANT
SKIPLE T3 ;HUH?
HRRE T3,JBTCX##(T3) ;OWNER
POPJ P,
;HERE TO GRANT CX TO A JOB AT SCHEDULAR LEVEL
SCDCX:: HLRE T3,JBTCX##(J) ;GET THE CX WE WANT
JUMPLE T3,CPOPJ1## ;HUH?
SYSPIF ;GUARD RACES
HRL T3,JBTCX##(T3) ;MAKE SURE IT'S STILL FREE
TLNE T3,-1 ;SOMEONE SNEAK IN?
JRST ONPOPJ## ;YES, LOSE
HRRM J,JBTCX##(T3) ;WE OWN HIS
AOS (P)
JRST ONPOPJ## ;WIN
;SUBROUTINE FOR CLOCK1 TO CALL TO SEE IF JOB IN J OWNS ANY CX RESOURCES
;SKIP RETURN IF OWN SOME CX, NON-SKIP OTHERWISE
OWNCX:: PUSH P,T1 ;SAVE T1
HLRZ T1,JBTCX##(J) ;OWN ANYTHING?
JUMPN T1,TPOPJ1##
JRST TPOPJ##
;ROUTINE TO SEE IF WE OWN THE CX. NON-SKIP IF WE DON'T, SKIP
;IF WE DO. CX DESIRED IN T1
CXOWN:: CAMN T1,.CPCXJ## ;OWNED BY CPU?
JRST CPOPJ1## ;YES
PUSH P,T2
HRRZ T2,JBTCX##(T1) ;SEE WHO OWNS HIS CX
CAMN T2,.CPJOB## ;US?
AOS -1(P) ;YES
JRST T2POPJ##
SUBTTL ROUTINES TO REFERENCE USER CORE
;GETTAC -- RE-LOAD AC T1 FROM USER'S AC ON A CALLI OR
;THE LIKE, IN CASES WHERE T1 HAS BEEN DESTROYED.
;CALL:
;
; MOVE J,JOB NUMBER
; PUSHJ P,GETTAC
; RETURN
;
;ON RETURN THE USER'S AC IS IN T1. USES M, PRESERVES ALL OTHER ACS.
;CALL GETSAC FOR THE SAME RESULTS, EXCEPT GETWSU IS CALLED INSTEAD OF GETWDU
GETTAC::LDB T1,PUUOAC## ;GET USER'S AC NUMBER
HRR M,T1 ;PROVIDE AS ADDRESS TO READ
PJRST GETWDU ;GO READ THE AC
GETSAC::LDB T1,PUUOAC## ;GET USER'S AC NUMBER
HRR M,T1
PJRST GETWSU
;GETWDU -- READ 1 WORD FROM USER VIRTUAL ADDRESS SPACE
;GETWD1 -- READ NEXT WORD FROM USER VIRTUAL ADDRESS SPACE
;CALL IS:
;
; MOVEI M,<ADR>
; PUSHJ P,GETWDU
; RETURN
;
;WHERE <ADR> IS USER VIRTUAL ADDRESS TO BE READ.
;
;DISPATCHES TO PAGE FAULT HANDLER ON A USER PAGE FAULT, OR PRINTS ILL
;ADR IN UUO IF NO SUCH ADDRESS.
;
;ON SUCCESSFUL RETURN THE USER WORD IS IN T1 AND, IF CALL WAS TO
;GETWD1 M IS UPDATED TO NEW USER VIRTUAL ADDRESS <ADR>+1. J IS SET
;TO THE USER'S JOB NUMBER. ALL OTHER ACS PRESERVED.
GETWD1::HRRI M,1(M) ;INCREMENT M BEFORE PICKING UP WORD
GTWST2::
GETWDU::MOVE J,.CPJOB## ;MAKE SURE J CORRECT
PUSHJ P,GETWRD ;GET THE WORD AND CHECK IF LEGAL
JRST @[MCSEC0+UADERR##] ;ADDRESS NOT ACCESSIBLE, PRINT ERROR
POPJ P, ;OK RETURN, T1=WORD
;GETWSU -- READ 1 WORD FROM USER VIRTUAL ADDRESS SPACE
;GETWS1 -- READ NEXT WORD FROM USER VIRTUAL ADDRESS SPACE
;SAME CALL AND RETURN AS GETWRD/GETWR1, BUT STOPCODES IF
;THE ADDRESS IS NOT AVAILABLE, AND DOES NOT LOAD J FROM .CPJOB
GETWS1::HRRI M,1(M)
GETWSU::PUSHJ P,GETWRD
CAIA ;SEE IF MUST STOP
POPJ P,
PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
JRST @[MCSEC0+UADERR##] ;NO, ADDRESS CHECK
STOPCD .,STOP,GNA ;++GETWRD NOT AVAILABLE
;GETWRD -- READ 1 WORD FROM USER VIRTUAL ADDRESS SPACE
;GETWR1 -- READ NEXT WORD FROM USER VIRTUAL ADDRESS SPACE
;CALL IS:
;
; MOVX J,<JOB>
; MOVX M,<ADR>
; PUSHJ P,GETWRD
; ERROR
; NORMAL
;
;WHERE <JOB> IS USER JOB NUMBER AND <ADR> IS USER VIRTUAL ADDRESS.
;CAN BE CALLED AT CLOCK OR UUO LEVEL.
;
;DISPATCHES TO PAGE FAULT HANDLER ON A USER PAGE FAULT, OTHERWISE
;RETURNS CPOPJ0 IF USER ADDRESS IS INACCESSIBLE.
;
;SUCCESSFUL RETURN IS CPOPJ1 WITH USER WORD IN T1 AND, IF CALL WAS
;TO GETWR1, WITH M INCREMENTED TO NEW USER VIRTUAL ADDRESS <ADR>+1.
;ALL OTHER ACS ARE PRESERVED.
IFN FTXMON,<
GETEW1::JUMPL M,GETWR1 ;SKIP OVERHEAD FOR IFIW FORMS
AOS T1,M ;INCREMENT GLOBAL ADDRESS
TRNE T1,-1 ;DID IT CROSS A SECTION BOUNDARY?
JRST GETEWD ;NO, DON'T BOTHER WITH THIS
PUSHJ P,SXPCS ;YES, BUMP PCS TO KEEP IT CONSISTENT
POPJ P, ;PROPAGATE FAILURES
GETXWD::!
GETEWD::JUMPL M,GETWRD ;SKIP OVERHEAD FOR IFIW FORMS
TDNN M,[^-<(IFIW!<1,,0>)>,,^-17] ;AN AC REFERENCE?
JRST GETWRA ;YES, GO HANDLE AC REFERENCE
SE1ENT ;MUST BE IN SECTION 1 FOR EACALC TO WORK
UMOVE T1,@M ;NOT AN AC, FETCH FROM USER SPACE
ERJMP GETWRY ;HANDLE ERRORS
JRST CPOPJ1## ;RETURN GOODNESS
GETMWD::LDB T1,[POINT 5,M,17] ;WHAT WE WANT PCS TO BE
PUSHJ P,SVPCS## ;SAVE AND SETUP PCS
PJRST GETWRD ;GET THE WORD
> ;END OF IFN FTXMON
IFE FTXMON,<
GETEW1::!
>
GETWR1::HRRI M,1(M) ;INCREMENT M BEFORE PICKING UP WORD
IFE FTXMON,<
GETXWD::!
GETEWD::!
GETMWD::!
> ;END OF IFE FTXMON
GETWRD::TRNN M,777760 ;REFERENCE TO A USER AC?
JRST GETWRA ;YES, HANDLE DIFFERENTLY
GETWRU: MOVE T1,M
IFN FTXMON,<
TLZ T1,-1-MXSECN
TRNN T1,777760 ;AC REFERENCE?
TLZ T1,MXSECN ;YES, CLEAR POSSIBLE SECTION NUMBER
>
UMOVE T1,(T1)
ERJMP GETWRY ;IF FAILED CHECK FOR PAGE FAULT ETC.
JRST CPOPJ1## ;TAKE SKIP RETURN
GETWRA::MOVE T1,J ;JOB NUMBER OR JCH
ANDI T1,JOBMSK## ;JUST JOB NUMBER
SKIPE .USJOB ;IF UPMP IS SETUP,
MOVE T1,.USJOB ;MAKE SURE OF OUR JOB NUMBER
MOVE T1,JBTSTS##(T1) ;JOB STATUS FOR THIS JOB
TRNN T1,JS.ASA ;REAL OR FAKE ACS?
JRST GETWRU ;REAL, HANDLE NORMALLY AFTER ALL
HRRZ T1,M ;CLEAR LEFT HALF JUNK
MOVE T1,.JDAT(T1) ;FAKE, READ FROM SHADOW ACS AREA
JRST CPOPJ1## ;SUCCESSFUL RETURN
GETWRY: MOVE R,.CPADR## ;SET UP RELOCATION FOR VMSER
PUSH P,J ;SAVE POSSIBLE JCH
ANDI J,JOBMSK## ;MASK IT DOWN FOR VMSER
SKIPE .USJOB ;IF WE'RE NOT FROM THE BOWELS OF THE SWAPPER,
MOVE J,.USJOB ;MAKE SURE OF OUR JOB NUMBER
PUSHJ P,FLTSY## ;CHECK FOR PAGE FAULT
JRST JPOPJ## ;BAD ADDRESS-ERROR RETURN
JRST JPOPJ## ;IT'S STILL BAD, FLTSY NOTWITHSTANDING
;STOTAC -- STORE WORD INTO USER AC
;STOTC1 -- STORE WORD INTO USER AC AND SKIP RETURN
;CALL IS:
;
; MOVX T1,<WRD>
; PUSHJ P,STOTAC
; RETURN (STOTAC)
; RETURN (STOTC1)
;
;WHERE <WRD> IS THE WORD TO BE WRITTEN INTO THE USER AC.
;
;PRESERVES ALL ACS.
STOTC1::AOSA (P) ;SKIP RETURN
RTM2:: MOVNI T1,2 ;RETURN -2 TO USER
STOTAC::PUSH P,M ;SAVE M
MOVS M,.USMUO ;GET MUUO OPCODE,AC IN LH
LDB M,PUUOAC## ;GET USER'S AC
PUSHJ P,PUTWDU ;STORE T1 IN USER'S AC
JRST MPOPJ## ;RESTORE M AND RETURN
;PUTWDU -- WRITE 1 WORD INTO USER VIRTUAL ADDRESS SPACE
;PUTWD1 -- WRITE NEXT WORD INTO USER VIRTUAL ADDRESS SPACE
;CALL IS:
;
; MOVX M,<ADR>
; MOVX T1,<WRD>
; PUSHJ P,PUTWDU
; RETURN
;
;WHERE <WRD> IS THE WORD TO BE WRITTEN INTO USER VIRTUAL ADDRESS <ADR>
;
;DISPATCHES TO PAGE FAULT HANDLER ON A USER PAGE FAULT, OR PRINTS ILL
;ADR IN UUO IF NO SUCH ADDRESS.
;
;ON SUCCESSFUL RETURN THE USER WORD IS IN T1 AND, IF CALL WAS TO
;PUTWD1 M IS UPDATED TO NEW USER VIRTUAL ADDRESS <ADR>+1.
;PRESERVES ALL OTHER ACS.
IFN FTXMON,<
PUTEW1::JUMPL M,PUTWR1 ;DO OLD WAY IF IFIW FORM
AOS M ;INCREMENT GLOBAL ADDRESS
TRNE M,-1 ;CROSSING A SECTION BOUNDARY?
JRST PUTEWD ;NO, SKIP THIS
PUSHJ P,SMPCS ;BUMP PCS FOR THIS FETCH
POPJ P, ;PROPAGATE FAILURES
PUTXWD::!
PUTEWD::JUMPL M,PUTWRD ;DO OLD WAY IF IFIW FORM
TDNN M,[^-<(IFIW!<1,,0>)>,,^-17] ;AN AC REFERENCE?
JRST PUTWRD ;YES, DO IT THE OLD WAY
SE1ENT ;MUST BE IN SECTION 1 FOR EACALC TO WORK
UMOVEM T1,@M ;NOT AN AC, STORE TO USER SPACE
ERJMP PUTWRZ ;HANDLE ERRORS
JRST CPOPJ1## ;RETURN GOODNESS
PUTMWD::PUSHJ P,SSPCS## ;PRESERVE PCS
PUSH P,T1 ;SAVE WORD TO STORE
LDB T1,[POINT 5,M,17] ;WHAT WE WANT PCS TO BE
PUSHJ P,STPCS## ;SAVE AND SETUP PCS
POP P,T1 ;RESTORE DATA WORD
PJRST PUTWRD ;STORE THE WORD
> ;END OF IFN FTXMON
PUTWD1::HRRI M,1(M) ;INCREMENT M BEFORE STORING WORD
PUTWDU::PUSH P,J ;SAVE J
MOVE J,.CPJOB## ;SET UP J FOR THIS CPU'S JOB
PUSHJ P,PUTWRD ;STORE THE WORD
JRST @[MCSEC0+UADERR##] ;A LOSER
JRST JPOPJ## ;A WINNER, RESTORE J AND RETURN
;PUTWSU -- WRITE 1 WORD INTO USER VIRTUAL ADDR SPACE
;PUTWS1 -- WRITE NEXT WORD
;CALL AND RETURN SAME AS PUTWDU/PUTWD1, BUT STOPCODES IF THE WORD ISN'T
;ADDRESSABLE AND DOES NOT LOAD J FROM .CPJOB
PUTWS1::HRRI M,1(M)
PUTWSU::PUSHJ P,PUTWRD
CAIA ;SEE IF MUST STOP
POPJ P,
PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
JRST @[MCSEC0+UADERR##] ;NO, ADDRESS CHECK
STOPCD .,STOP,PNA ;++PUTWRD NOT AVAILABLE
;PUTWRD -- WRITE 1 WORD INTO USER VIRTUAL ADDRESS SPACE
;PUTWR1 -- WRITE NEXT WORD INTO USER VIRTUAL ADDRESS SPACE
;CALL IS:
;
; MOVX J,<JOB>
; MOVX M,<ADR>
; MOVX T1,<WRD>
; PUSHJ P,PUTWRD
; ERROR
; NORMAL
;
;WHERE <JOB> IS USER JOB NUMBER; <ADR> IS USER VIRTUAL ADDRESS;
;AND <WRD> IS THE WORD TO BE WRITTEN INTO THE USER ADDRESS <ADR>.
;CAN BE CALLED AT CLOCK OR UUO LEVEL.
;
;DISPATCHES TO PAGE FAULT HANDLER ON A USER PAGE FAULT, OTHERWISE
;RETURNS CPOPJ0 IF USER ADDRESS IS UNWRITEABLE.
;
;SUCCESSFUL RETURN IS CPOPJ1 WITH USER WORD IN T1 AND, IF CALL WAS
;TO PUTWR1, WITH M INCREMENTED TO NEW USER VIRTUAL ADDRESS <ADR>+1.
;ALL OTHER ACS PRESERVED.
IFE FTXMON,<
PUTEW1::!
>
PUTWR1::HRRI M,1(M) ;INCREMENT BEFORE STORING WORD
IFE FTXMON,<
PUTEWD::!
PUTMWD::!
>
PUTWRD::PUSH P,T1 ;NEED A SCRATCH AC MOMENTARILY
TRNN M,777760 ;REFERENCE TO USER AC?
JRST PUTWRA ;YES, HANDLE DIFFERENTLY
HRRZ T1,M ;GET USER VIRTUAL ADDRESS
CAIG T1,JOBPFI## ;IN PROTECTED JOB DATA AREA?
JRST TPOPJ## ;YES, TAKE FAILURE RETURN
PUTWRU: POP P,T1 ;RESTORE VALUE TO BE DEPOSITED
IFN FTXMON,<
PUSH P,M
TLZ M,-1-MXSECN
TRNN M,777760 ;AN AC REFERENCE?
TLZ M,MXSECN ;YES, CLEAR POSSIBLE SECTION NUMBER
>
UMOVEM T1,(M) ;STORE WORD IN USER ADDRESS SPACE
ERJMP PUTWRY ;CHECK ON FAILURE
IFN FTXMON,<
POP P,M
>
JRST CPOPJ1## ;TAKE SUCCESSFUL RETURN
PUTWRA: MOVE T1,J ;JOB NUMBER OR JCH
ANDI T1,JOBMSK## ;JUST JOB NUMBER
SKIPE .USJOB ;IF UPMP IS SETUP,
MOVE T1,.USJOB ;MAKE SURE OF OUR JOB NUMBER
MOVE T1,JBTSTS##(T1) ;JOB STATUS FOR THIS JOB
TRNN T1,JS.ASA ;REAL OR FAKE ACS?
JRST PUTWRU ;REAL, TREAT NORMALLY AFTER ALL
POP P,T1 ;FAKE ACS, RESTORE T1
PUSH P,M
TLZ M,-1-MXSECN ;CLEAR POSSIBLE JUNK
MOVEM T1,.JDAT(M) ;AND WRITE INTO SHADOW ACS
POP P,M
JRST CPOPJ1## ;ALWAYS SUCCEEDS
PUTWRY:
IFN FTXMON,<
POP P,M ;RESTORE ORIGINAL CONTENTS
>
PUTWRZ: PUSH P,J ;SAVE POSSIBLE JCH FROM MOLESTATION
ANDI J,JOBMSK## ;USE ONLY JOB NUMBER IN FLTSY AND HGHDEP
SKIPE .USJOB ;IF UPMP SETUP,
MOVE J,.USJOB ;MAKE SURE OF OUR JOB NUMBER
PUSH P,.USPFW ;SAVE PAGE FAIL WORD
PUSHJ P,FLTSY## ;CHECK FOR PAGE FAULT
JRST [POP P,(P) ;FIX STACK
JRST JPOPJ## ] ;BAD ADDRESS
EXCH T1,(P) ;SAVE T1, GET ADDRESS
PUSH P,T2 ;SAVE T2
PUSH P,S ;PROTECT AGAINST
PUSH P,P2 ; HGHDEP
MOVE S,-3(P) ;HGHDEP WANTS WORD IN S
MOVE T2,T1 ;AND ADDRESS IN T2
PUSH P,M ;MORE AC PROTECTION
SNCALL (HGHDEP##,MCSEC0) ;TRY STUFFING INTO HIGH SEGMENT
SOS -5(P) ;NOPE
POP P,M ;RESTORE M
POP P,P2 ;RESTORE
POP P,S ; ACS
POP P,T2 ; FROM
POP P,T1 ; HGHDEP
JRST JPOPJ1## ;RESTORE JCH WINNINGLY
;WARNING: ANY CHANGES MADE TO TSTREL SHOULD ALSO BE REFLECTED IN GETWRD & PUTWRD
TSTREL::MOVEI T1,JS.ASA ;WHAT DOES REFERENCE TO USER 0-17 REALLY MEAN BIT
TRNN M,777760 ;IS THIS REFERENCE TO USER 0-17?
TDNN T1,JBTSTS##(J) ;YES, IS IT TO USER'S ACS OR THE SHADOW ACS?
AOS (P) ;USER'S ACS
POPJ P, ;GIVE SHADOW ACS OR USER AC SET RETURN
SUBTTL USER ARGUMENT SECTION ROUTINE
;ROUTINE TO SETUP FOR FETCHING USER ARGUMENTS FROM ARBITRARY SECTIONS
;RESPECTS BOTH 30-BIT ADDRESS (REALLY ONLY 23-BIT) AND IFIW FORMS,
;BUT WITH NEITHER INDEXING NOR INDIRECTION.
;CALLING SEQUENCE:
; MOVE T1,[USER ADDRESS ARGUMENT, EITHER 30-BIT OR IFIW]
; PUSHJ P,SXPCS
; RETURN NON-SKIP ON ANY SORT OF ADDRESSING ERROR
; SKIP RETURN WITH PCS SETUP APPROPRIATELY IF EVERYTHING IS OK
;RESPECTS ALL ACS
SMPCS:: EXCH T1,M ;SAME CALL, WITH ADDRESS IN M
PUSHJ P,SXPCS ;DO THE DIRTY WORK
CAIA ;NON-SKIP
AOS (P) ;OR SKIP
EXCH T1,M ;RESTORE ACS
POPJ P, ;PROPAGATE RETURN
SXPCS:: SKIPGE T1 ;IF AN IFIW,
TLNN T1,^-<(IFIW)> ;CHECK IF
TLNE T1,^-<(IFIW!<MXSECN,,0>)> ;ANY ATTEMPT AT INDEXING OR INDIRECTION?
POPJ P, ;YES, RETURN FAILURE
IFN FTXMON,<
JUMPL T1,CPOPJ1## ;IF IFIW, PCS IS ALREADY CORRECT
PUSH P,T1 ;SAVE T1 FOR CALLER
HLRZS T1 ;ISOLATE SECTION NUMBER IN RH
PUSHJ P,STPCS## ;SETUP PCS AS DESIRED
JRST TPOPJ1## ;RETURN AS ADVERTISED
>
IFE FTXMON,<JRST CPOPJ1##> ;RETURN GOODNESS IF NO XMON
;SUBROUTINE TO CHECK IF SEGMENT # IN J IS A LEGAL SEG #
;ARGS J=SEG#
;SKIP RETURN IF LEGAL SEGMENT #, NON-SKIP IF NOT
LGJSEG::HRRZ T1,J
LGLSEG::CAILE T1,JOBMAX## ;SKIP IF BELOW 1ST LEGAL SEG #
CAIL T1,JBTMAX## ;NO, SKIP IF LEGAL SEG #
POPJ P,
JRST CPOPJ1##
LGJPRC::SKIPA T1,J ;FROM J, EXCLUDE ZERO
LGJPR1::SKIPA T1,J ;FROM J, ALLOW ZERO
LGLPRC::JUMPLE T1,CPOPJ## ;JUMP IF LE 0
LGLPR1::CAIG T1,JOBMAX##
JUMPGE T1,CPOPJ1## ;0 WAS ALREADY CHECKED
POPJ P, ;-N ALWAYS ILLEGAL
;SUBROUTINE TO CREATE A PDB
;ARG J=JOB NUMBER
$HIGH
CREPDB::HRRZ W,JBTPDB##(J) ;SEE IF ALREADY ONE THERE
JUMPE W,CREPD1 ;NONE
PUSHJ P,SAVE4## ;SAVE COMCON FROM CTXSER'S DESTRUCTIVENESS
PUSHJ P,CTXKIL## ;KILL OFF CONTEXT BLOCKS
JRST CREPD2 ;ZERO OUT THE PDB
CREPD1: MOVEI T2,.PDLEN## ;NUMBER OF WORDS NEEDED FOR A PDB
PUSHJ P,GETWDS## ;GET CORE FOR PDB
POPJ P, ;CAN'T GET THRU
HRRZ W,T1 ;COPY ADDRESS TO STANDARD AC
HRRM W,JBTPDB##(J) ;SAVE PDB ADDRESS
CREPD2: SETZM (W) ;CLEAR ALL PDB
MOVSI T1,(W) ;MAKE BLT PTR
HRRI T1,1(W)
BLT T1,.PDLEN##-1(W)
MOVE T1,STNPRT## ;INITIALIZE DEAFULT
MOVEM T1,.PDDFL##(W) ;TO STANDARD FILE PROTECTION
MOVSI T1,(PD.LGN) ;GET THE LOGIN BIT
IORM T1,.PDDFL##(W) ;SET IT IN THE WORD
PUSHJ P,CTXBLK## ;CREATE AN INITIAL CONTEXT BLOCK
JRST KILPDB ;NOT ENOUGH CORE
PUSHJ P,ENQJBI## ;INIT QUEUE LIST HEADER
JRST CPOPJ1## ;RETURN
;SUBROUTINE TO DEALLOCATE A PDB
;ARGS J=JOB NUMBER
KILPDB::JUMPE J,CPOPJ## ;NEVER DELETE THE NULL JOB'S PDB
IFN FTMP,<
PUSHJ P,INTLVL## ;INTERRUPT LEVEL?
JRST [EXCH T1,J ;UPCX WANTS ARG IN T1
PUSHJ P,UPCX ;NO, WAIT UUO LEVEL STYLE
EXCH T1,J
JRST KILPD1 ]
PUSHJ P,GETCX
JRST .-1 ;INTERRUPT LEVEL STYLE
KILPD1:
> ;END IFN FTMP
HRRZ W,JBTPDB##(J) ;GET PDB ADDRESS
JUMPE W,KILPD2 ;MUST HAVE ONE TO DELETE IT
PUSHJ P,CTXKIL## ;GO CLEAN UP OLD CONTEXT BLOCKS
MOVEI T1,.PDLEN## ;NUMBER OF WORDS FOR A PDB
HRRZ T2,JBTPDB##(J) ;ADDR OF PDB
PUSHJ P,GIVWDS## ;DEALLOCATE PDB
KILPD2: HLLZS W,JBTPDB##(J) ;CLEAR ADDR OF PDB
IFN FTMP,<
PUSHJ P,INTLVL## ;INTERRUPT LEVEL?
PJRST DWNCX ;GIVE IT UP UUO LEVEL STYLE
PJRST GIVCX ;RETURN CX RESOURCE
> ;END IFN FTMP
IFE FTMP,<POPJ P,> ;RETURN
$CSUB
SUBTTL UUO ARGUMENT BLOCK CHECKING ROUTINES -- ARNGE - ADDRESS CHECKING
; ROUTINE TO PERFORM ADDRESS CHECKING ON UUO ARGUMENT BLOCKS.
; THIS HANDLES ALL CASES OF 30-BIT ADDRESSES AND IFIW WORDS.
; IT MAY ONLY BE CALLED AT UUO LEVEL.
;
; IF THE RANGE OF ADDRESSES CROSSES A SECTION BOUNDRY AND THE
; TARGET GIVEN WAS AN IFIW, THEN ADDRESS CHECK ERROR WILL BE
; RETURNED. OTHERWISE, A GLOBAL RANGE OF ADDRESSES WHICH CROSSES
; SECTION BOUNDRIES WILL BE CONSIDERED LEGAL.
;
; THE RANGE OF ADDRESSES IS CONSIDERED ILLEGAL FOR I/O IF ANY
; PAGE IN THE RANGE IS NOT MARKED AS WRITEABLE IN A PAGE MAP.
; ALSO, IF ANY PAGE IN THE RANGE IS MAPPED TO SECTION ZERO
; PAGE ZERO AND ANY ADDRESS RELATIVE TO THAT PAGE IS LESS THAN
; JOBPFI, THE RANGE WILL BE CONSIDERED ILLEGAL FOR I/O.
;
; CALL: MOVE T1, STARTING ADDRESS
; MOVE T2, LENGTH OF BLOCK
; PUSHJ P,ARNGE
; <RETURN 1> ;ADDRESS CHECK
; <RETURN 2> ;ADDRESS OK BUT ILLEGAL FOR I/O
; <RETURN 3> ;ADDRESS OK
;
; PCS AND ALL ACS ARE PRESERVED
ARNGE:: PUSH P,T1 ;SAVE T1
PUSH P,T2 ;SAVE T2
PUSH P,T3 ;SAVE T3
PUSH P,T4 ;SAVE T4
PUSHJ P,ARNGE1 ;DO SOME WORK
JRST ARNGEX ;ADDRESS CHECK ERROR
AOS -4(P) ;ALL PAGES CHECKED OUT OK
SKIPN T1 ;ANY PAGES ILLEGAL FOR I/O?
AOS -4(P) ;YES
ARNGEX: POP P,T4 ;RESTORE T4
POP P,T3 ;RESTORE T3
POP P,T2 ;RESTORE T2
POP P,T1 ;RESTORE T1
POPJ P, ;RETURN
ARNGE1: SE1ENT ;ENTER SECTION 1
IFN FTXMON,<PUSHJ P,SSPCS##> ;SAVE PCS
PUSHJ P,SXPCS ;SET NEW PCS
POPJ P, ;BAD ARGUMENTS--ADDRESS CHECK ERROR
PUSH P,T1 ;SAVE ADDRESS (WITH POSSIBLE IFIW)
XSFM T3 ;GET PCS
ANDI T3,MXSECN ;STRIP OFF JUNK
HRL T1,T3 ;REPLACE POSSIBLE IFIW WITH REAL SECTION NUMBER
ADD T2,T1 ;COMPUTE END ADDRESS +1
SUBI T2,1 ;LAST ADDRESS TO CHECK
HLRZ T3,T1 ;GET STARTING SECTION NUMBER
HLRZ T4,T2 ;AND ENDING SECTION NUMBER
EXCH T1,(P) ;GET POSSIBLE IFIW BACK
CAIE T3,(T4) ;CROSS SECTION ?
JUMPE T3,TPOPJ## ;ILLEGAL FROM SECTION 0
CAIE T3,(T4) ;CROSS SECTION BOUNDRY?
JUMPL T1,TPOPJ## ;YES--ADDRESS CHECK ERROR IF AN IFIW GIVEN
MOVEI T1,0 ;CLEAR ILLEGAL I/O FLAG
EXCH T1,(P) ;SAVE AND RETRIEVE FULL 30-BIT ADDRESS
PUSHJ P,INTLVL## ;ARE WE AT UUO LEVEL?
TDNE T2,[^-1,,^-17] ;AND IS ENDING ADDRESS AN AC?
JRST ARNGE2 ;NO, SKIP THE SPECIAL CASE
CAMGE T2,T1 ;DO ADDRESSES GO BACKWARDS?
JRST TPOPJ## ;YES, FATAL
CAIN T3,(T4) ;IS ENTIRE RANGE IN THE ACS IN ONE SECTION?
JRST TPOPJ1## ;YES, THIS IS ALWAYS LEGAL EVEN FOR I/O
MOVEI T2,-1 ;NO, ONLY CHECK TO END OF S0 WHEN CROSSING
ARNGE2: HLRZ T3,T1 ;GET SECTION NUMBER
CAIG T3,MXSECN ;HAVE A REASONABLE SECTION NUMBER?
SKIPN .UPMP+SECTAB(T3);AND DOES THE SECTION EXIST?
JRST TPOPJ## ;NO--ADDRESS CHECK ERROR
MOVE T3,T1 ;COPY TARGET ADDRESS
LSH T3,W2PLSH ;CONVERT TO A PAGE NUMBER
HRRZ T4,T1 ;GET RELATIVE ADDRESS WITHIN SECTION
CAILE T4,JOBPFI## ;IN PROTECTED JOBDAT?
JRST ARNGE3 ;NO
MOVE T4,@[IW MS.MAP,UMAPS(T3)] ;POINTER FOR PAGE 0 OF PCS SECTION
CAMN T4,@[IW MS.MAP,UMAPS] ;SAME AS POINTER FOR PAGE 0 OF SECTION 0?
AOS (P) ;ADDRESS ILLEGAL FOR I/O
ARNGE3: SKIPN T4,@[IW MS.MAP,UMAPS(T3)] ;GET POINTER FOR THIS PAGE
JRST TPOPJ## ;NON-EXISTANT--ADDRESS CHECK ERROR
ARNGE4: TLNE T4,(PM.NIA!PM.SPY) ;I/O LEGAL?
AOS (P) ;NO--SAY ILLEGAL FOR I/O
LDB T3,[POINT 3,T4,2] ;GET POINTER TYPE
JUMPE T3,ARNGE6 ;PAGED OUT, AA OFF, OR ABZ--PAGE FAULT
CAIN T3,PM.DCD ;ELSE IS IT A DIRECT POINTER?
JRST ARNGE5 ;YES
CAIE T3,PM.ICD ;INDIRECT POINTER?
JRST [HRRZS T4 ;NO, SHARED, GET SPT INDEX
SKIPN T4,SPTTAB##(T4) ;GET POINTER
JRST TPOPJ## ;ADDRESS CHECK ERROR IF NONE
JRST ARNGE4] ;LOOP OVER POINTERS
LDB T3,[POINT 9,T4,17] ;GET INDEX INTO SECONDARY PAGE MAP
HRRZS T4 ;GET SPT INDEX
HRRZ T4,SPTTAB##(T4) ;GET POINTER TO USE FROM SPT
JUMPE T4,TPOPJ## ;FAIL IF SPT SLOT NOT SETUP
TLO T4,(<PM.DCD>B2) ;MAKE VALID MAPPING ENTRY
PUSH P,.UPMP+.UMTMP ;SAVE TEMPORARY MAPPING SLOT
MOVEM T4,.UPMP+.UMTMP ;STORE MAP POINTER
TRO T3,.TEMP ;MAKE FULL ADDRESS FOR FETCH
CLRPT .TEMP ;CLEAR PAGING MEMORY SO NEW MAPPING IS USED
MOVE T4,@T3 ;GET MAP ENTRY
POP P,.UPMP+.UMTMP ;RESTORE TEMPORARY MAPPING SLOT
CLRPT .TEMP ;CLEAR PAGING MEMORY SO OLD MAPPING IS USED
JUMPN T4,ARNGE4 ;CHASE DOWN MAP POINTER
JRST TPOPJ## ;FAIL IF NEXT SLOT IN CHAIN IS ZERO
ARNGE6: PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
JRST @[MCSEC0+UUOFLT##] ;NO, LET PFH HAVE IT
AOS (P) ;YES, CONSIDER IT ILLEGAL FOR I/O
; JRST ARNGE5 ;KEEP ON TRUCKING AT INTERRUPT LEVEL
ARNGE5: TRO T1,PG.BDY ;ROUND UP TO TOP OF PAGE
CAML T1,T2 ;PAST THE END OF THE BLOCK
JRST TPOPJ1## ;YES--ALL ADDRESSES CHECK OUT OK
ADDI T1,PAGSIZ ;ON TO THE NEXT PAGE
JRST ARNGE2 ;LOOP BACK
SUBTTL UUO ARGUMENT BLOCK CHECKING ROUTINES -- PRNGE - BYTE POINTER
; CHECK A RANGE OF ADDRESSES GIVEN A BYTE POINTER
; CALL: MOVE T1, BYTE POINTER
; MOVE T2, BYTE COUNT
; PUSHJ P,PRNGE
; <RETURN 1> ;ADDRESS CHECK
; <RETURN 2> ;ADDRESS OK BUT ILLEGAL FOR I/O
; <RETURN 3> ;ADDRESS OK
;
; PCS AND ALL ACS EXCEPT T1-T3 ARE PRESERVED
PRNGE:: IBP T1 ;POINT TO FIRST REAL BYTE
SOJ T2, ;OFFSET FOR IBP ABOVE
ADJBP T2,T1 ;POINT AT END
LDB T3,[POINT 6,T1,5] ;GET BYTE POSITION
CAILE T3,^D36 ;OWGBP?
TLZA T1,(77B5) ;YES
HRLI T1,(IFIW) ;OR NO
CAILE T3,^D36 ;AGAIN?
TLZA T2,(77B5) ;GLOBAL
HRLI T2,(IFIW) ;OR LOCAL ADDRESS
SUB T2,T1 ;FINALLY, MAKE A COUNT FOR ARNGE
AOJA T2,ARNGE ;GO RANGE CHECK THE BLOCK
SUBTTL UUO ARGUMENT BLOCK CHECKING ROUTINES -- QRNGE - BYTE POINTER
; CHECK A RANGE OF ADDRESSES GIVEN A BYTE POINTER
; CALL: MOVE T1, BYTE POINTER WORD 1
; MOVE T2, BYTE POINTER WORD 2
; MOVE T3, BYTE COUNT
; MOVE M, ADDRESS OF SCRATCH LOCATION FOR PUTEWD
; PUSHJ P,QRNGE
; <RETURN 1> ;ADDRESS CHECK
; <RETURN 2> ;ADDRESS OK BUT ILLEGAL FOR I/O
; <RETURN 3> ;ADDRESS OK
;
; PCS AND ALL ACS EXCEPT T1-T4 ARE PRESERVED
; T1 & T2 HAVE A RESOLVED BYTE POINTER IN THEM ON RETURNS 2 & 3
;
;NOTE THAT THE SCRATCH LOCATION REQUIRED IS USUALLY THE ADDRESS FROM WHICH
;THE SECOND WORD OF THE BYTE POINTER WAS FETCHED.
;
;NOTE ALSO THAT THE RESOLVED BYTE POINTER RETURNED WILL HAVE CONVERTED A
;OWGBP INTO A TWO-WORD GLOBAL, EVEN IF PCS IS ZERO. IF YOU WANT TO USE
;THE BYTE POINTER DIRECTLY IN A PXCT, CALL ORNGE INSTEAD.
;
;ORNGE REQUIRES THAT RETURNS 2 & 3 LEAVE T3 NON-NEGATIVE.
QRNGE:: LDB T4,[POINT 6,T1,5] ;PICK UP P OR P&S FIELD
IFE FTXMON,<
CAIG T4,44 ;IS THIS A OWGBP?
JRST QRNGE2 ;NO, MUST BE LOCAL-SECTION
>
IFN FTXMON,<
CAILE T4,44 ;IS THIS A OWGBP?
JRST QRNGE1 ;YEP--GO BREAK IT DOWN
XSFM T4 ;GET PCS
SKIPN T4 ;IF FROM SECTION ZERO,
TLZA T1,(1B12) ;CAN'T BE TWO-WORD FORMAT
TLNN T1,(1B12) ;IS IT IN TWO-WORD FORMAT?
JRST QRNGE2 ;NO--MUST CONVERT
TLNE T1,37 ;IS THE RESERVED FIELD IN USE?
POPJ P, ;YES--THIS IS ILLEGAL
JRST QRNGE3 ;GO EVALUATE ADDRESS
> ;END OF IFN FTXMON
QRNGE1: CAIL T4,77 ;IS IT LEGAL EVEN FOR A OWGBP?
POPJ P, ;NO--CRY FOUL
MOVE T2,T1 ;COPY BYTE POINTER (FOR ADDRESS)
MOVE T1,OWGBPT-45(T4);GET LH OF EQUIVALENT BYTE POINTER
TLZ T2,(77B5) ;ISOLATE ADDRESS
JRST QRNGE4 ;GO CHECK OUT ADDRESS
QRNGE2: MOVE T2,T1 ;COPY BYTE POINTER (FOR ADDRESS)
TLZ T2,^-37 ;GET RID OF P & S FIELDS
TLO T2,(IFIW) ;MAKE SECTION LOCAL
TLZ T1,77 ;KEEP ONLY P & S FIELDS IN FIRST WORD
QRNGE3: EXCH T1,T2 ;SWAP WORDS FOR A BIT
PUSHJ P,PUTEWD ;STUFF ADDRESS WORD
JRST [EXCH T1,T2 ;SWAP BACK
POPJ P,] ;GIVE ERROR RETURN
HRRZ T1,M ;GET ADDRESS POINER FOR EACALC
PUSHJ P,EACALC ;GET EFFECTIVE ADDRESS FROM BYTE POINTER VALUE
JRST [EXCH T1,T2 ;SWAP BACK
POPJ P,] ;PROPAGATE ERROR
EXCH T1,T2 ;SWAP B.P. VALUES BACK AGAIN
HLLZS T1 ;CLEAR POSSIBLE JUNK
QRNGE4: TLNN T1,(1B12) ;IS THIS A TWO-WORD POINTER?
HRR T1,T2 ;NO, KEEP A VALID ONE-WORD FORM FOR DECNET
PUSH P,T1 ;SAVE THE BYTE POINTER
PUSH P,T2 ;AS A DOUBLE-WORD
LDB T4,[POINT 6,T1,11] ;GET S FIELD
CAILE T4,44 ;IS IT REASONABLE?
JRST TTPOPJ## ;NO--AVOID IME
JUMPE T4,TTPOPJ## ;DISALLOW ZERO-SIZED BYTES
MOVEI T1,^D36 ;YES, GET WORD SIZE
IDIVI T1,(T4) ;SEE HOW MANY BYTES FIT IN A WORD
LDB T2,[POINT 6,-1(P),5] ;GET P FIELD
EXCH T2,T3 ;MOVE FOR SAFETY
IDIVI T3,(T4) ;SEE HOW MANY BYTES IN FIRST WORD
SUB T2,T3 ;COUNT OF BYTES BEYOND FIRST WORD
MOVE T4,T3 ;SAVE FIRST WORD COUNT
IDIVI T2,(T1) ;COUNT OF ADDITIONAL WORDS REFERENCED
SKIPE T3 ;IF ANY REMAINDER,
AOS T2 ;REFERENCE ANOTHER WORD
SKIPE T4 ;IF ANY IN FIRST WORD,
AOS T2 ;REFERENCE IT TOO
SKIPE T4 ;IF ANY IN FIRST WORD,
TDZA T1,T1 ;THEN START THERE
MOVEI T1,1 ;ELSE START ONE AFTER IT
ADD T1,(P) ;FORM BEGINNING ADDRESS TO CHECK
PUSHJ P,ARNGE ;CHECK THE WORDS
JRST TTPOPJ## ;ILLEGAL ADDRESS IN RANGE
TRNA ;READ ONLY
AOS -2(P) ;PROPAGATE SKIPNESS
AOS -2(P) ;SINGLE OR DOUBLE
JRST TTPOPJ## ;AND RETURN MUNGED BYTE POINTER WORDS
OWGBPT:
DEFINE X(SIZ),<
IRP SIZ,<
.ZZ==-1
REPEAT ^D<36/<SIZ>>+1,<
<POINT <SIZ>,,.ZZ>!IFN FTXMON,<1B12>
.ZZ==.ZZ+^D<SIZ>
>
>
>
X<6,8,7,9,18>
OWGTLN==.-OWGBPT ;LENGTH OF THIS TABLE
IF2,<PURGE .ZZ>
SUBTTL UUO ARGUMENT BLOCK CHECKING ROUTINES -- ORNGE - BYTE POINTER
; CHECK A RANGE OF ADDRESSES GIVEN A BYTE POINTER
; CALLING SEQUENCE IS IDENTIAL TO THAT OF QRNGE, WHICH IS CALLED.
;
; ON RETURNS 2 & 3, A RESOLVED BYTE POINTER WILL BE RETURNED. THIS BYTE
; POINTER WILL BE IN ONE-WORD FORMAT IF POSSIBLE. IT WILL BE A ONE-WORD
; GLOBAL IFF T3 IS NEGATIVE.
ORNGE:: PUSHJ P,QRNGE ;RESOLVE THE BYTE POINTER
POPJ P, ;PROPAGATE FAILURE
TRNA ;ILLEGAL FOR I/O RETURN
AOS (P) ;PROPAGATE SKIPNESS
AOS (P) ;SINGLE OR DOUBLE
IFN FTXMON,<
TLNN T1,(1B12) ;TWO-WORD FORMAT?
JRST ORNGE3 ;NO, RETURN ONE-WORD LOCAL
JUMPL T2,ORNGE2 ;CONVERT TWO-WORD LOCAL TO ONE-WORD LOCAL
XSFM T3 ;GET PCS (AMONG OTHER THINGS)
TSC T3,T2 ;XOR SWAPPED
TRNN T3,MXSECN ;GLOBAL ADDRESS IN CURRENT SECTION?
JRST ORNGE2 ;YES, CONVERT TO ONE-WORD LOCAL
MOVSI T3,-OWGTLN ;GET AOBJN POINTER TO OWGBPT CONVERSION TABLE
ORNGE1: CAME T1,OWGBPT(T3) ;IS THIS A MATCH?
AOBJN T3,ORNGE1 ;NO, KEEP LOOKING
JUMPGE T3,CPOPJ## ;OH, WELL, WE'RE STUCK WITH A TWO-WORD GLOBAL
HRRZI T1,45(T3) ;GOT A MATCH, CONVERT TO P&S BYTE
LSH T1,^D30 ;POSITION IT
IOR T1,T2 ;GET ONE-WORD FORM
POPJ P, ;RETURN
ORNGE2: TLZ T1,(1B12) ;NOT REALLY GLOBAL AFTER ALL
> ;END OF IFN FTXMON
ORNGE3: HRR T1,T2 ;MAKE ONE-WORD LOCAL
POPJ P, ;RETURN
SUBTTL UUO ARGUMENT CHECKING - DECNET-STYLE STRING BLOCK
;
; CHKSTB - CHECK A STRING BLOCK FOR ADDRESSABILITY
;
;CALL: M/ ADDRESS OF STRING BLOCK
;
;RETURN: +1 NOT WRITEABLE OR READABLE
; +2 SUCCESS. MAX BYTE COUNT IN T4
;
;SIDE-EFFECTS:
; THE BYTE-COUNT IN THE STRING BLOCK IS ZEROED, FOR CONVENIENCE
; IN DEALING WITH ERRORS.
IFN FTNET,<
CHKSTB::MOVE T1,M ;GET ADDRESS OF BLOCK
IFN FTXMON,<PUSHJ P,SSPCS##> ;PRESERVE PCS FOR CALLER
PUSHJ P,SXPCS ;VALIDATE POINTER TO STRING BLOCK
POPJ P, ;NO GO
PUSHJ P,GETEWD ;GET FIRST WORD OF STRING BLOCK
POPJ P, ;NOT THERE
HRRZ T2,T1 ;SAVE LENGTH (IN WORDS)
MOVE T1,M ;GET ADDRESS OF BLOCK
PUSHJ P,ARNGE ;CHECK IT
POPJ P, ;NOT ADDRESSABLE
POPJ P, ;NOT WRITEABLE
MOVE T1,T2 ;GET LENGTH IN RIGHT AC
PUSHJ P,PUTEWD ;AND STUFF IT BACK WITH A 0 LH
POPJ P, ;NOT WRITABLE?
SOS T4,T1 ;ONE LESS THAN THIS AVAILABLE FOR BYTES
LSH T4,2 ;4 BYTES PER WORD
JRST CPOPJ1## ;OK
> ;END IF IFN FTNET
SUBTTL UUO ARGUMENT BLOCK CHECKING ROUTINES -- EACALC - EFFECTIVE ADDR CALC
; ROUTINE TO DO EFFECTIVE ADDRESS CALCULATION ON A UUO ARGUMENT.
; CALL: MOVE T1, SECTION RELATIVE UVA CONTAINING WORD FOR EACALC
; PUSHJ P,EACALC
; <NON-SKIP> ;ILLEGAL ADDRESS REFERENCED
; <SKIP> ;T1 HAS RESOLVED ADDRESS
;
; THE WORD MAY BE EFIW OR IFIW AND OPTIONALLY CONTAIN LOCAL OR
; GLOBAL INDEXING AND INDIRECTION. ON RETURN, T1 WILL CONTAIN
; THE RESOLVED USER VIRTUAL ADDRESS. NO LEGALITY CHECKS ARE MADE
; ON THE ADDRESS. PRESEUMABLY, SOME FLAVOR OF GETWRD/PUTWRD WILL
; TAKE CARE OF ADDRESS CHECKING. ALL ACS ARE PRESERVED.
EACACC::MOVE T1,JBTSTS##(J) ;GET JOB STATUS
SNCALL (USCHD1##,MCSEC0) ;LET USER CONTROL-C OUT
SKIPA T1,(P) ;GET UVA BACK
EACALC::PUSH P,T1 ;SAVE UVA
HRLI T1,(XMOVEI T1,@);FORM INSTRUCTION
; HERE TO DO ACTUAL EFFECTIVE ADDRESS CALCULATION. KAF STOPCODES ARE
; AVOIDED BY HAVING CLOCK1 (CLKINT) CHECK THE INTERRUPTING PC. IF IT
; IS EACAPC, THEN THE SCHEDULER WILL RUN. INFINITE LOOPS IN EXEC MODE
; WHERE THE USER CAN'T CONTROL-C OUT ARE AVOIDED BY CHECKING CNTRLC IN
; JBTSTS AND ALTERING THE INTERRUPTING PC TO BE EACACC, THUS ALLOWING
; THE USER TO REACH MONITOR LEVEL THE NEXT TIME THE JOB IS SCHEDULED.
EACAPC::PXCT PX.EAC,T1 ;LET HARDWARE DO EFFECTIVE ADDRESS CALCULATION
ERJMP .+2 ;NON-SKIP FOR ILLEGAL ADDRESS REFERENCE
AOS -1(P) ;ADDRESS OK
POP P,(P) ;PRUNE STACK
POPJ P, ;AND RETURN
SUBTTL SUBROUTINES TO REFERENCE PHYSICAL MEMORY
;ROUTINE TO FETCH THE CONTENTS OF A GIVEN PHYSICAL ADDRESS.
;CALL:
; T2/ PHYSICAL ADDRESS
; PUSHJ P,PHMOV
;RETURN:
; CPOPJ ALWAYS WITH:
; T2/ CONTENTS
;MUST PRESERVE T1 AND T3.
$CSENT (PHMOV::)
SKIPE .CPPMV## ;INSTRUCTION IMPLEMENTED?
JRST [PMOVE T2,T2 ;YES, FETCH THE CONTENTS
POPJ P,] ;RETURN
PUSHJ P,SAVE3## ;SAVE P1-P3
DMOVE P1,T1 ;COPY T1 AND T2
MOVE P3,T3 ;AND T3
PUSHJ P,MAPLOC## ;GET A MAP SLOT TO USE
DPB P2,[POINT 9,T3,35] ;SET LINE IN PAGE
LSH P2,W2PLSH ;CONVERT TO PAGE NUMBER
HRLI P2,(<PM.DCD>B2) ;MAKE IT ACCESSIBLE
DPB P2,T1 ;STORE MAPPING IN EXEC PAGE MAP
CLRPT .ERPIL ;MAKE THE NEW MAPPING VISIBLE
MOVE T2,0(T3) ;FETCH THE CONTENTS
PUSHJ P,UNMAP## ;GIVE UP THE MAP SLOT
MOVE T1,P1 ;RESTORE T1
MOVE T3,P3 ;AND T3
POPJ P, ;RETURN
;ROUTINE TO STORE DATA INTO A GIVEN PHYSICAL ADDRESS.
;CALL:
; T2/ PHYSICAL ADDRESS
; T3/ DATA TO STORE
; PUSHJ P,PHMOVM
;RETURN:
; CPOPJ ALWAYS
;MUST PRESERVE T1 AND T3.
$CSENT (PHMOVM::)
SKIPE .CPPMV## ;INSTRUCTION IMPLEMENTED?
JRST [PMOVEM T3,T2 ;YES, STORE THE CONTENTS
POPJ P,] ;RETURN
PUSHJ P,SAVE3## ;SAVE P1 - P3
DMOVE P1,T1 ;COPY T1 AND T2
MOVE P3,T3 ;COPY DATA TO STORE
PUSHJ P,MAPLOC## ;GET A MAP SLOT TO USE
DPB P2,[POINT 9,T3,35] ;SET LINE IN PAGE
LSH P2,W2PLSH ;CONVERT TO PAGE NUMBER
HRLI P2,(<PM.DCD>B2!PM.WRT) ;MAKE IT ACCESSIBLE AND WRITABLE
DPB P2,T1 ;STORE MAPPING IN EXEC PAGE MAP
CLRPT .ERPIL ;MAKE THE NEW MAPPING VISIBLE
MOVEM P3,0(T3) ;STORE THE DATA
PUSHJ P,UNMAP## ;GIVE UP THE MAP SLOT
MOVE T1,P1 ;RESTORE T1
MOVE T3,P3 ;AND T3
POPJ P, ;RETURN
$LIT
DATEND: END